直方图使用Excel FREQUENCY功能

时间:2012-03-06 08:16:28

标签: excel histogram frequency

在Excel 2010中,我在列A中有一个值列表,并在B1中指定了一个bin大小。这允许我使用以下公式创建具有N个bin的直方图:

{=FREQUENCY(A:A,(ROW(INDIRECT("1:"&CEILING((MAX(A:A)-MIN(A:A))/B1,1)))-1)*B1+MIN(A:A))}

唯一的问题是我需要选择 N个单元并应用此公式来获取N个bin作为条形图的数据源。可以跳过这一步吗?例如。是否可以在单个单元格中使用此公式 - 稍微修改一下 - 这样当用作数据源时,它被解释为N个单元格,产生一个带N值的漂亮直方图?

感谢。

Here's the answer that led me to the formula above.

2 个答案:

答案 0 :(得分:7)

(这与宏驱动动态范围调整大小的方法完全不同,所以我使用单独的答案......)

动态直方图可以通过记住“命名范围”实际命名为公式来构建,因此它们的值可能是动态的,在某些情况下非常如此。

让我们假设我们在A列中有一组任意值,从第1行开始,并且我们还有另一个包含我们在直方图中需要的bin数的单元格。在我的工作簿中恰好是E2。因此,我们启动名称管理器(在“公式”选项卡上)并创建

num_bins             =Sheet1!$E$2

我已经去定义了一些bin,而不是bin大小(我们稍后会定义),因为后者让我们很难确切地知道如何设置bin边界:我们是否满意这个想法第一个和最后一个箱可以覆盖该值范围的不同大小的部分,例如?*

我们还可以设置动态公式来描述我们的数据:

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)

这就是科学:这些公式构成了动态数组:

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 - 大小范围的行号来生成bin_size的倍数。它不会在min_val处启动数组,因为FREQUENCY()函数会计算每个bin值的项目。它比所需的二进制数小一个因为该函数产生一个更大的数组,其中最后一个条目的点高于最高的二进制数。因此,我们为演示目的制作了一个单独的bin_labels数组。

现在我们可以制作图表了。插入(比方说)二维柱形图并打开“选择数据”对话框(从功能区或右键单击图表)。添加新系列,将系列值设置为=Sheet1!freq_array。必须包含工作表名称或工作簿名称才能使其工作。如果您愿意,可以添加系列名称,然后单击“确定”。现在单击“水平(类别)轴标签”的“编辑”,并将范围设置为=Sheet1!bin_labels

这是2000个带有=RAND()*5和5个分区的单元格(我列出了名称及其公式,其值不会产生数组)

2000 <code>=RAND()*5</code> results into 5 bins

将num_bins更改为10之后的相同工作表。(重新计算了RAND()个公式,因此这些二进制数可能无法合计完全相同的值)

After changing num_bins to 10

  • (如果您必须拥有用户定义的二进制文件大小,则需要使用bin_size工作表参考并使用命名公式计算num_bins

答案 1 :(得分:0)

我能想到的唯一答案是使用宏来调整公式的输出范围。

这是一个简单的片段,说明了这个想法。

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

我去年写了a more complete implementation - 更容忍错误,二维输出等等

编辑:但是......您使用的公式不适用于此方法:它依赖于输入时已知的输出范围大小。这是一个可以自动调整大小的替代建议:

我们可以使用以下内容创建一组可行的垃圾箱:

={(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()创建一个范围(目标无关紧要,因为我们没有使用它的值)。然后我们取范围内每个单元格的ROW()(减去1得到一组从零开始的值)并乘以我们的bin大小。您可能希望更改值的范围(例如,通过添加MIN(A:A))。

最大的区别在于,无需在Evaluate() VBA函数的范围内输入此公式,以便能够生成范围输出。

要获得直方图,请将bin公式的输出插入FREQUENCY()或插入整个公式。自动调整大小应该都可以。

如果您特别反对运行宏(我可以通过自定义功能区按钮和热键组合使用它),那么您可以使用Worksheet_Change事件来监视应用它的机会。我不能确定这是否会产生任何不愉快的副作用。