使用Excel FREQUENCYfunction的直方图
在Excel 2010中,列A
有一个值列表,并且在B1
指定了一个bin大小。 这使我可以使用这个公式创buildN个bin的直方图:
{=FREQUENCY(A:A,(ROW(INDIRECT("1:"&CEILING((MAX(A:A)-MIN(A:A))/B1,1)))-1)*B1+MIN(A:A))}
唯一的问题是我需要select N个单元格并应用此公式来获取N个元素作为我的条形图的数据源。 有没有可能跳过这一步? 例如,是否有可能在单个单元格中使用此公式(稍加修改),以便在用作数据源时将其解释为N个单元格,从而生成一个N值良好的直方图?
谢谢。
这是让我看到上面的公式的答案。
(这与macros观驱动的dynamic范围调整方法的方法相当不同,所以我使用单独的答案…)
可以通过记住“命名范围”实际上是命名公式来构builddynamic直方图图表,因此它们的值可能是dynamic的,在某些情况下非常重要。
让我们从假定我们在A列中有一个任意的值集合开始,并且我们有另一个单元格,它包含我们想要在我们的直方图中的分箱数量。 在我的工作手册中,碰巧是E2。 所以我们启动名称pipe理器(在“公式”选项卡上)并创build
num_bins =Sheet1!$E$2
我已经定义了一些箱子,而不是箱子的大小(我们将在后面定义),因为后者使得我们很难确切地知道如何设置箱子的边界:我们对这样的想法感到满意:最后一个分箱可能覆盖值范围的不同大小的部分,例如?*
我们也可以设置dynamic公式来描述我们的数据:
data_count =COUNT(Sheet1!$A:$A) data_vals =OFFSET(Sheet1!$A$1,0,0,data_count,1) max_val =MAX(data_vals) min_val =MIN(data_vals)
随着那些定义,我们可以看中。 每个垃圾桶应该多大? 制作另一个命名公式:
bin_size =(max_val-min_val)/(num_bins)
科学就是这样:这些公式构成了dynamic数组:
bin_array =min_val+ROW(OFFSET(Sheet1!$A$1,0,0,num_bins-1,1))*bin_size bin_labels =min_val+ROW(OFFSET(Sheet1!$A$1,0,0,num_bins,1))*bin_size data_vals =FREQUENCY(data_vals,bin_array)
第一个更复杂:它使用num_bins minus one
的行号num_bins minus one
-size范围来生成bin_size
。 它不会在min_val
处启动数组,因为FREQUENCY()
函数min_val
数直到每个bin值的项目。 它比所希望的箱子数目要小,因为函数产生了一个更大的数组,其中最后一个入口具有高于最高箱子数目的点。 所以我们为演示目的制作一个单独的bin_labels
数组。
现在我们可以制作一个图表。 插入一个(比如说)二维柱形图并打开“select数据”对话框(可以从function区或右键单击图表)。 添加一个新系列,将系列值设置为=Sheet1!freq_array
。 有必要包含工作表名称或工作簿名称以使其工作。 如果您喜欢,请添加系列名称,然后单击“确定”。 现在单击“编辑”为“水平(类别)轴标签”,并将范围设置为=Sheet1!bin_labels
。
这里是2000个单元格,其中=RAND()*5
和5个分档(我列出了名称和它们的公式,其中不产生数组的值)
并且在将num_bins更改为10后重新计算RAND()
公式,因此可能不会加上完全相同的值)
- (如果您必须具有用户定义的bin大小,则需要使用
bin_size
表参考并使用指定的公式计算num_bins
)
我能想到的唯一答案是使用macros来调整公式的输出范围。
这里有一个简单的片段来说明这个想法。
Dim result As Variant Dim targetCols As Long result = Evaluate(fmla) With rng targetCols = UBound(result, 1) - LBound(result, 1) + 1 .Resize(1, targetCols).FormulaArray = fmla End With
去年我写了一个更完整的实现 – 更多的容错,二维输出等等
编辑:但是…你正在使用的公式不会使用这种方法:它依赖于input的输出范围大小。 这是一个可以自动resize的替代build议:
我们可以用这样的东西创build一组可用的垃圾箱:
={(ROW(OFFSET(A1,0,0,CEILING((MAX(A:A)-MIN(A:A))/B1,1)+1,1))-1)*B1}
在此之前,这是箱的数量
CEILING((MAX(A:A)-MIN(A:A))/B1,1)+1
然后我们使用OFFSET()
创build一个范围OFFSET()
由于我们没有使用它的值,因此目标无关紧要)。 然后,我们将每个单元格的ROW()
(减去1得到一组以零开始的值)并乘以我们的bin大小。 您可能想要移动值的范围(例如通过添加MIN(A:A)
)。
最大的区别是,这个公式不需要在Evaluate()
VBA函数的范围内input,以便能够生成范围输出。
要获得直方图,可以将bin公式中的输出插入FREQUENCY()
或放入整个公式中。 自动resize应该可以工作。
如果您特别反对运行macros(我可以通过自定义function区button和热键组合),那么您可以使用Worksheet_Change
事件来监视应用它的机会。 我不能肯定地说这是否会有不愉快的副作用。