從資料列中減去子集平均值的公式?我正在尋找一種方法來獲取僅使用與指定條件匹配的行的數據表的子集,並從列中減去這些行的平均值。
例如,使用 Big Class 資料集,假設我想建立一個新列來顯示“該學生與 14 歲同性別平均身高之間的差異。”
我知道如何做到這一點的方法是添加第二個表,使用表 - >摘要 - >統計:平均值(身高),組:性別,子組:年齡。 然後我可以 Table -> Update: Big Class By (sex), Match columns: 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 中意味著我只想考慮年齡=14 的行,而不是使用與該行關聯的年齡值。
我非常頻繁地進行這種類型的標準化,因此任何可以使其更快、更容易的方法都將受到極大的讚賞!
資料混合與清理回覆:從資料列中減去子集平均值的公式?美麗的! 謝謝!!!
回覆:從資料列中減去子集平均值的公式?你好@MarkJSchwab ,
是的,我可以看到在許多情況下用條件語句包裝它可能並不理想。 這是一個修改@brady_brady應該有效的解決方案(附表):

testVal = :sex;
:height - Mean( :height[(:height << get datatable) << get rows where( :age == 14 & :sex == testVal )] );
在本例中,我們取得目前行的 :sex 值,並將其儲存到變數 testVal 中。 然後,當我們評估居中函數時,我們可以測試在 get rows where() 函數中使用該值。
以下表格的一列僅包含此 Get RowsWhere() 函數選擇的行:

正如您所看到的,所有行都使用年齡 14 作為子集,但哪個性別子集由性別的當前行值決定。 應該很容易適應不同程度的複雜性。
@朱利安
回覆:從資料列中減去子集平均值的公式?您只需擴展公式即可處理男性和女性
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" )] )
)
回覆:從資料列中減去子集平均值的公式?你好@朱利安再次感謝您的幫忙!
最後一個難題:理想情況下,我希望從女孩中減去 14 歲女孩的平均年齡,從男孩中減去 14 歲男孩的平均年齡。 (在您的示例中,您從男孩和女孩中減去 14 歲女孩的年齡。)
(我意識到在這種特定情況下,只有 M/F 就很容易使用條件,並說“如果 :sex == 'F' 則使用此公式,如果 :sex == 'M' 則將公式修改為說{mean(:height[(:height << get datatable) << get rows where( :age == 14 & :sex == "M" )])}" 但在我更一般的用例中,我可能有一個大量的群組和嵌套條件會變得難以處理。)
有什麼簡單的方法可以實現這個目標嗎?
回覆:從資料列中減去子集平均值的公式?你好@MarkJSchwab ,
它確實出現了 <
這是 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"

現在我們有了一個與您的條件相符的行矩陣,Brady 使用該矩陣作為下標: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 !
@朱利安
回覆:從資料列中減去子集平均值的公式?你好@朱利安,謝謝你的建議。 不幸的是,當我貼上那個確切的公式時
Col Mean( :height, <<FREQ></FREQ>
進入我的大類,它返回 62.55(即沒有選擇年齡 = 14 的總體 Col 平均值),而不是您看到的正確值 64.166。
我甚至可以下載您的附件,正確的值會顯示在「以年齡==14 時的平均值為中心」欄位中。 但是,如果我在該表中使用完全相同的公式創建一個新列,它會返回不同的值(顯示[高度] - [總體平均高度],而不是正確顯示[高度] - [14歲的平均高度])。
我使用的是 JMP Pro 14.3.0。 關於如何使我的輸出與您的輸出相符有什麼想法嗎?
還有一個問題,如果您在工作表上新增一個額外的byVar :sex (對於總公式“:height - (Col Mean( :height, :sex, <回覆:從資料列中減去子集平均值的公式?
你好@MarkJSchwab ,
有一種使用 Col Mean() 的簡單方法可以做到這一點,但在您看到它之前並不明顯。 Col Mean() 採用頻率列參數:

通常,這是當您需要使用另一列進行加權時的情況。 但是,在您的範例中,如果我們可以將 Age==14 的值加權為 1,將所有其他值加權為 0,會怎麼樣? 這將為我們提供年齡==14 的個體的平均值。 我們可以直接用公式來實現:
Col Mean( :height, <<FREQ></FREQ>

這將返回:

現在,對於您的特定問題,以高度的特定平均值為中心,我們可以按照通常的方式將其包裝到公式中:
:height - (Col Mean( :height, <<FREQ></FREQ>


我希望這有幫助!
@朱利安
回覆:從資料列中減去子集平均值的公式?嗨,馬克·施瓦布!
當然,有一種方法可以做你想做的事。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 的好資源!
祝你好運!