エントリが別の列 B の最後の 10 個の非 null エントリの平均/中央値/最頻値に等しい列 A を作成するにはどうすればよいですか?こんにちは、
数値と多くの null 値 (おそらく 70-80% null) を持つ列 A (約 15,000 行) があります。
行 i で次の平均に等しい列 B を作成したいと思います: *A からの最後の 10 個の非 null 値*
--> これは、 A[row i-1] 、 A[row i-2]、... を取り、10 個の非 null 値が得られるまで戻ることを意味します (または、行 1 に到達した場合は、任意の数 <= 10 を取ります)取得する null 以外の値)
また、平均に加えて、中央値とモードも実行したいと思いますが、モードの平滑化されたバージョンは次のとおりです。
まず、10 個の非 null 値のガウス平滑化を行い、その分布の argmax (モード) を取得します。
考えや提案をありがとう!
***
ソリューションのアイデア: 最後の 10 個の非 null 値を使用していくつかの異なる計算を実行したいので、最初に、最後の 10 個の非 null 値に等しい配列をエントリとする列 C を作成する必要があるため、私が考えたのは 1 つです。列 C を操作して B1 (平均)、B2 (中間)、B3 (平滑化モード) を生成する 3 つの数式を実行できます。
この列 C の配列の構築に向けて進んでいるコードの一部を次に示します。
//step 1 grab the last say 50 entries (some fixed amount that will likely have 10 non-nulls)
For Each Row( dt_join,
to = Row();
If( to - 50 < 0,
from = 1,
from = to - 50); // Quantile( 0.5,
values = :away_1g_pull_seconds[Index( From, To )] < 50, Break());
);
//step 2 convert array to list, drop nulls, convert list of first 10 entries back to array ...
//I don't know how to assign this to a row of C
num_lag = 10;
values = dt_join:A[Index( From, To )] ;
MyList = Remove(as list(values)[1], as list(Loc(as list(values)[1], .)) ); //convert array to list and remove nulls
Mat = Number Col Box("", MyList[1:10]) << get as matrix; //hack convert to array
データ表スクリプティングRe: エントリが別の列 B の最後の 10 個の非 null エントリの平均/中央値/最頻値に等しい列 A を作成するにはどうすればよいですか?これが最初のリクエストの始まりです。列Aの最後の10個の値の平均を作成し、その平均を列Bに入れます
今はこれ以上作業する時間がありません。たぶん今週末以降。
Names Default To Here( 1 );
dt = Current Data Table();
theMatrix = [];
dt << New Column( "B" );
For Each Row(
If( Is Missing( :A ) == 0,
theMatrix = Matrix( :a ) || theMatrix
);
If( Length( theMatrix ) > 10,
theMatrix[1, 11] = []
);
:B = Mean( theMatrix );
);
Re: エントリが別の列 B の最後の 10 個の非 null エントリの平均/中央値/最頻値に等しい列 A を作成するにはどうすればよいですか?@ドンマコーマックこれは良いチャレンジ問題になります。
これは機能し、かなり効率的だと思います。
nr = 15000;
dt = New Table( "Untitled",
Add Rows( nr ),
New Column( "a", Numeric, "Continuous", Format( "Best", 12 ), Set Values( J( nr, 1, If( Random Uniform() < .3, Random Integer( 0, 1 ), . ) ) ) )
);
lookback = 10;
dt << New Column( "b" || Char( lookback ),
formula(
// make a helper to help look up the non-missing rows
helper = As Constant( // AsConstant is for efficiency
temp = dt << getrowswhere( !Is Missing( a ) );
// temp is the non-missing row numbers. Make sure row 1
// is included, even if missing, because LocSorted will
// return [1] when a smaller value would have been better.
If( temp[1] != 1,
Insert Into( temp, 1, 1 )
);
temp; // this is assigned to 'helper'
);
currentrow = Row(); // this is the target for a new mean, etc
end = Loc Sorted( helper, currentrow )[1]; // end is the last non missing row before or at the target
start = Max( 1, end - lookback + 1 ); // start is the row 'lookback' rows earlier
rowset = helper[start :: end]; // rowset is the set of nonmissing rows, possibly including a missing value at row 1.
// it is OK if a missing value is present; mean/median/mode ignore it.
// grab the rowset from column a and report the statistic...
Mean( dt[rowset, {a}] );// median, mode
)
);
Re: エントリが別の列 B の最後の 10 個の非 null エントリの平均/中央値/最頻値に等しい列 A を作成するにはどうすればよいですか?こんにちは、
これを行う別の方法として、欠落のない中間テーブルを使用する方法があります。これにより、より単純な式が可能になります。
Names Default To Here( 1 );
dt = Current Data Table();
//get nonmissing rows of table and put them in a new table
m = dt << get rows where( !Is Missing( :a ) );
dt2 = New Table( "xxx", invisible, <<ADD rows=""></ADD>
元のテーブルが小さい場合 (あなたのもののように... 約 15K 行)、2 つのアプローチは同様に実行されます。最初の方法は少し高速です。

元のテーブルが大きくなるにつれて、「別のテーブル」アプローチのスケールの方がかなり優れているように見え、約 1/10 の時間で実行されます。 150K 行の例を次に示します。

考えられる問題 (??) は、このアプローチではソース テーブルに式が生成されないため、新しいデータが追加されるたびにこれを再実行する必要があることです。
実験したい場合に備えて、150K 行のファイルを添付しました。
乾杯、
ブレイディ
Re: エントリが別の列 B の最後の 10 個の非 null エントリの平均/中央値/最頻値に等しい列 A を作成するにはどうすればよいですか?その他の結果を次に示します。 「個別」の方法は、直線的にスケーリングしているようです。 「同じテーブル」メソッドは、450,000 行の北のどこかで壁にぶつかるようです。 理由はわかりません。


Re: エントリが別の列 B の最後の 10 個の非 null エントリの平均/中央値/最頻値に等しい列 A を作成するにはどうすればよいですか?helper=AsConstant の場合はまだ N^2 だと思います。 それは100K配列を400K回コピーすることになります...
編集:推測が確認されました。 しかし、式からヘルパーを取り除いても、私のコードは Brady のコードの約半分の速さになります。
しかし...ジムのコードは微調整してより高速にすることができます...
dt = Current Data Table();
startTime = Tick Seconds();
theMatrix = {., ., ., ., ., ., ., ., ., .};
z = .;
dt << New Column( "B" );
dt << begindataupdate;
For Each Row(
v = :A;
If( v == v,
Insert Into( theMatrix, v );
Remove From( theMatrix, 1 );
z = Mean( theMatrix );
);
:B = z;
);
stopTime = Tick Seconds();
Show( stopTime - startTime );
dt << enddataupdate;Re: エントリが別の列 B の最後の 10 個の非 null エントリの平均/中央値/最頻値に等しい列 A を作成するにはどうすればよいですか?すべての回答に感謝します - 私は圧倒されました!
詳細を読む機会はありませんでしたが、読んだらもっと返信します。
一番、
ジョー
Re: エントリが別の列 B の最後の 10 個の非 null エントリの平均/中央値/最頻値に等しい列 A を作成するにはどうすればよいですか?それは本当に素晴らしいです。私のアプローチよりもはるかにエレガントです。
Re: エントリが別の列 B の最後の 10 個の非 null エントリの平均/中央値/最頻値に等しい列 A を作成するにはどうすればよいですか?うわー……この演習は私にたくさんのことを教えてくれましたか。私の元のコードは機能しましたが、別の方法よりもはるかに遅かったので、時間をかけてそれらを研究しました。非常に高速で巧妙なコード。それで@Craige_Hales彼の最新のコードを提供しました。これは非常に高速ですが、私の元のコードに非常に近いアプローチをとっています。@Craige_Halesコードははるかに高速です。そして、違いのほとんどは、私が使用していないことです
Begin Data Update;
.....
End Data Update;
そのため、更新が終了するまで更新メッセージを保持してくれたことに大きな感謝をしています。
楽しませてくれてありがとう!