這似乎是一個容易解決的問題,但我有點卡住了。
我有一個包含 250 行和大約 20K 列的數據集。 這些行分為兩類:好(249 行)和壞(1 行)。 我需要找到所有列,其中“BAD”行的值高於/低於其餘“GOOD”行的值。
你能建議任何有效的方法嗎?
謝謝!
@D_T_M ,
@txnelson , Jim,為您提供了一個很好的、易於遵循的解決方案,可以使用 JMP 界面和列函數完成。下面是使用 JSL 和矩陣的替代解決方案。
我不確定哪種方法的性能最好。 如果您不熟悉 JMP 矩陣表示法或 JSL,請將此回複視為供 JMP 社區其他人參考的信息。
Names Default To Here( 1 );
// Create a simple data table for illustration
dt = New Table( "simple",
Add Rows( 10 ),
New Column( "A", Set Values( [59, 66, 55, 66, 52, 60, 61, 51, 60, 61] ) ),
New Column( "B",
Format( "Fixed Dec", 5, 0 ),
Set Values( [123, 22, 74, 145, 64, 84, 128, 79, 112, 107] )
),
New Column( "C",
Set Values( [96, 110, 100, 92, 92, 97, 98, 94, 91, 94] ),
)
);
cnames = dt << get column names("string"); //need to remove column names that are not to be tested<BR />//typically cnames = cnames[n::n+249999]
//Matrix of bad row - assuming you know which row is bad, row 2.
bmat = dt[2,1::3];
glist = Remove( AsList(1::nrow(dt))[1], 2);
gmax = V Max(dt[ glist, 1::3 ]); //returns a row vector of each column max
gmin = V Min(dt[ glist, 1::3 ]); //returns a row vector of each column min
mxcol = loc(bmat - gmax > 0); //returns a row vector of column # where bmat > gmax
mncol = Loc(bmat - gmin < 0); //returns a row vector of column # where bmat < gmin
HiCol = cnames[transpose(mxcol)];
LoCol = cnames[transpose(mncol)];
show(HiCol, LoCol);
/*:
HiCol = {"C"};
LoCol = {"B"};假設您有一列標識第 1 個壞行和所有 249 個好行,這就是我的做法。
1. 堆疊所有 20k 行,保留標識壞行和所有好行的列
表==>堆棧
2.總結得到的Stacked table
一個。 按新列“標籤”分組
b. 按標識壞數據和好數據的列進行子分組
C。 指定計算“數據”列的最小值和最大值
3.在生成的匯總表中
一個。 使用公式添加一個名為“Min Max”的新列
If(
:Name( "Max(Data,Bad)" ) > :Name( "Max(Data,Good)" ), "Max",
:Name( "Min(Data,Bad)" ) < :Name( "Min(Data,Good)" ), "Min",
"Neither"
)
下面是將創建上述結果的示例腳本。它使用只有 4 列的示例數據表,但是,通過更改腳本中指向包含壞行和好行的列(在示例數據表中稱為“GoodBad”)的名稱,它將適用於您的 20k 表,到數據表中標識壞數據和好數據的列的名稱。
該腳本還假定要比較所有數字列。
Names Default To Here( 1 );
// Create a simple data table for illustration
dt = New Table( "simple",
Add Rows( 10 ),
New Column( "A", Set Values( [59, 61, 55, 66, 52, 60, 61, 51, 60, 61] ) ),
New Column( "B",
Format( "Fixed Dec", 5, 0 ),
Set Values( [22, 123, 74, 145, 64, 84, 128, 79, 112, 107] )
),
New Column( "C",
Set Values( [110, 96, 100, 92, 92, 97, 98, 94, 91, 94] ),
),
New Column( "GoodBad",
Character,
Set Values(
{"Bad", "Good", "Good", "Good", "Good", "Good", "Good", "Good", "Good", "Good"}
)
)
);
// Get All Numeric Columns
numericCols = dt << get column names(numeric);
// Stack all of the numeric
dtStack = dt << Stack(invisible,
columns( numericCols ),
Source Label Column( "Label" ),
Stacked Data Column( "Data" )
);
// Summarize the data
dtSum = dtStack << Summary(
Group( :Label ),
Min( :Data ),
Max( :Data ),
Subgroup( :GoodBad ),
Freq( "None" ),
Weight( "None" ),
Link to original data table( 0 )
);<BR /><BR />// Delete the no longer needed Stacked data table<BR />
<SPAN style="display: inline !important; float: none; background-color: #ffffff; color: #008000; font-family: Consolas,Monaco,'Andale Mono','Ubuntu Mono',monospace; font-size: 14px; font-style: normal; font-variant: normal; font-weight: 300; letter-spacing: normal; orphans: 2; text-align: left; text-decoration: none; text-indent: 0px; text-transform: none; -webkit-text-stroke-width: 0px; white-space: pre; word-spacing: 0px;">close( dtStack, nosave );</SPAN><BR />// Add the column that determines if Bad column is < or > Good
dtSum << New Column(
"Max or Min",
formula(
If(
:Name( "Max(Data,Bad)" ) > :Name( "Max(Data,Good)" ), "Max",
:Name( "Min(Data,Bad)" ) < :Name( "Min(Data,Good)" ), "Min",
"Neither"
)
)
);