从数据列中减去子集的平均值的公式?我正在寻找一种方法来获取仅使用符合指定条件的行的数据表的子集,并从列中减去这些行的均值。
例如,使用Big Class数据集,说我想创建一个新列,显示“该学生与同性别的平均14岁学生之间的身高差异。”
我知道如何执行此操作的方法是添加第二张表,方法是使用表->摘要->统计信息:均值(高度),组:性别,子组:年龄。 然后我可以在Table-> Update:Big Class By(性别)中,匹配列:sex = sex,这将为Mean(height,[age])添加几列。 然后,我可以创建一个新列“ Delta height vs 14yo of same sex”,即:height-:Mean(height,14)。
我的问题:没有创建额外的表和额外的列(例如“ Mean(height,14)”),有什么办法吗? 似乎Col Mean(x,byVar)即将提供此功能,但缺少选择其他组的功能;例如,我可以使用:height-Col Mean(:height,:age,:sex)查找学生X与自己性别和身高的普通学生之间的差异,但是我不知道是否有一种方法可以指定在Col中表示我只想考虑age = 14的行,而不要使用与该行关联的age值。
我经常进行这种类型的标准化,因此,使它变得更快和更容易的任何事情将不胜感激!
数据表回复:从数据列中减去子集的平均值的公式?嗨,MarkJSchwab!
当然,有一种方法可以做您想要的。JSL将让您自由!
我编写了一个简单的脚本,该脚本主要使用JSL的功能为您编写脚本。试试吧:
// Title: Bigclass Normalization Script for JMP User Community discussion
// Purpose: Demonstrate how to write a very basic script to do "normalizations"
Names Default To Here( 1 );
Bigclass_dt = Open( "$SAMPLE_DATA\Big Class.jmp" );
BigclassSummary_dt = bigclass_dt << Summary( Group( :age, :sex ), Mean( :height ) );
BigclassSummary_dt << Select Where( :Age != 14 ) << Delete Rows;
Bigclass_dt << Join(
With( BigclassSummary_dt ),
Select( :name, :age, :sex, :height ),
SelectWith( :Name( "Mean(height)" ) ),
By Matching Columns( :sex = :sex ),
Drop multiples( 0, 0 ),
Include Nonmatches( 0, 0 ),
Preserve main table order( 1 ),
Output Table( "NormedBigclass by AgeGender" )
);
BigclassJoin_dt = Data Table( "NormedBigclass by AgeGender" ) << New Column( "Normalized",
numeric,
continuous,
Formula( :Name( "height" ) - :Name( "Mean(height)" ) ),
evalFormula
);
Close( BigclassSummary_dt, NoSave );
我制作了一个单独的摘要表,然后将其关闭,但是您不必那样做。
当然,有类似这样的脚本编写方法,尤其是因为所有“ where”子句都是硬编码的,并且如果您的数据表很大,则可能会遇到此脚本问题,但是,即使是JSL,将是您提高生产力的途径。有很多学习JSL的资源!
祝你好运!
回复:从数据列中减去子集的平均值的公式?你好@MarkJSchwab ,
有一种使用Col Mean()进行操作的简单方法,除非您看到它,否则还不明显。 Col Mean()采用频率列参数:

通常,这是当您需要使用另一列进行加权时。 但是,在您的示例中,如果我们可以将Age == 14的值加权为1,将所有其他值加权为0,该怎么办? 这将使我们仅获得年龄== 14的那些人的平均值。 我们可以直接在公式中执行此操作:
Col Mean( :height, <<FREQ></FREQ>

这将返回:

现在,对于您的特定问题,以从高度开始的特定均值为中心,我们可以按通常方式将其包装到公式中:
:height - (Col Mean( :height, <<FREQ></FREQ>


我希望这有帮助!
@朱利安
回复:从数据列中减去子集的平均值的公式?你好@朱利安,感谢您的建议。 不幸的是,当我粘贴该确切公式时
Col Mean( :height, <<FREQ></FREQ>
进入我的大类,它将返回62.55(即不选择age = 14的总体Col Mean),而不是您看到的正确值64.166。
我什至可以下载您的附件,并且适当的值会显示在“相对于年龄平均值== 14居中”列中。 但是,如果我在该表中使用完全相同的公式创建新列,则会返回不同的值(显示[height]-[overall avg height],而不是正确显示[height]-[14yos的平均高度])。
我正在使用JMP Pro 14.3.0。 关于如何获得与您匹配的输出的任何想法?
还有一个问题,在表上,如果您添加一个额外的byVar:sex(对于总公式“:height-(Col Mean(:height,:sex,<< Freq(:age == 14)))”)从男孩中减去平均14yo男孩身高,然后从女孩中减去14yo女孩平均身高?
回复:从数据列中减去子集的平均值的公式?你好@MarkJSchwab ,
确实出现了<<在JMP 15中添加了频率作为可选参数的情况,因此对于JMP的早期版本,您将需要执行其他操作。
这是jmp向导的解决方案@brady_brady :
:height - Mean( :height[(:height << get datatable) << get rows where( :age == 14 )] )

值得花一点时间来解开这个公式,因为我敢打赌有些方法您以后会发现有价值。
(:height << get datatable) << get rows where( :age == 14 )
将返回行条目矩阵,其中:age == 14。 重要的是,您可以修改get rows where()函数以匹配所需的任何查找,包括第二个询问(我相信您要包含另一个变量)。 例如:
(:height << get datatable) << get rows where( :age == 14 & :sex == "F"

现在,我们有了一个符合您条件的行矩阵,布雷迪使用此矩阵对下标:height进行下标。
height[(:height << get datatable) << get rows where( :age == 14 & :sex == "F" )]

这将返回每行的:height值的矩阵,在这种情况下,将返回14岁女学生的身高:[61,62,65,63,62]
最后,Mean()函数围绕此矩阵包装,该矩阵返回您需要计算中心变量的均值:
mean(:height[(:height << get datatable) << get rows where( :age == 14 & :sex == "F" )])

该解决方案更加灵活,可以容忍丢失的数据,并且适用于jmp的早期版本,因此,我认为这是一个更好的解决方案。 谢谢, @brady_brady !
@朱利安
回复:从数据列中减去子集的平均值的公式?你好@朱利安再次感谢您的帮助!
最后的皱纹:理想情况下,我希望女孩平均减去14岁的女孩年龄,男孩平均减去14岁的男孩年龄。 (在您的示例中,您正在从男孩和女孩中减去14岁的女孩。)
(我意识到,在这种仅使用M / F的特定情况下,使用条件运算会很容易,然后说“如果:sex =='F',则使用此公式,如果:sex =='M',则将公式修改为说{mean(:height [(:height <<获取数据表)<<获取行where(:age == 14&:sex ==“ M”)])}“”,但在我更一般的用例中,我可能有一个大量的组和嵌套的条件将变得笨拙。)
任何简单的方法来实现这一目标?
回复:从数据列中减去子集的平均值的公式?您只需要扩展公式即可处理男性和女性
If( :sex == "F",
:height - Mean( :height[(:height << get datatable) << get rows where( :age == 14 & :sex == "F" )] ),
:height - Mean( :height[(:height << get datatable) << get rows where( :age == 14 & :sex == "M" )] )
)
回复:从数据列中减去子集的平均值的公式?你好@MarkJSchwab ,
是的,我可以看到在很多情况下将其包装在条件语句中可能并不理想。 这是对@brady_brady的解决方案(附表):

testVal = :sex;
:height - Mean( :height[(:height << get datatable) << get rows where( :age == 14 & :sex == testVal )] );
在这种情况下,我们获取当前行:sex的值,并将其保存到变量testVal中。 然后,当我们评估居中功能时,我们可以测试在get row where()函数中使用该值。
这是一个表,其中仅包含此Get Rows Where()函数选择的行的列:

如您所见,所有行都使用14岁作为子集,但是哪个性别子集由当前行的sex值确定。 应易于适应不同级别的复杂性。
@朱利安