Wie konstruiere ich eine Spalte A, deren Einträge gleich dem Mittelwert/Median/Modus der letzten 10 Nicht-Null-Einträge einer anderen Spalte B sind?Hallo,
Ich habe eine Spalte A (ca. 15.000 Zeilen), die Zahlen und viele Nullwerte enthält (vielleicht 70-80 % null).
Ich möchte eine Spalte B konstruieren, die in Zeile i gleich dem Mittelwert ist von: den * letzten 10 Nicht-Null-Werten von A *
--> das bedeutet, nimm A[Zeile i-1] , A[Zeile i-2], ... und gehe zurück, bis du 10 Nicht-Null-Werte hast (oder wenn du Zeile 1 erreichst, dann nimm eine beliebige Zahl <= 10 von Nicht-Null-Werten, die Sie erhalten)
Ich würde auch gerne zusätzlich zu Mittel, Median und auch Modus machen, aber eine geglättete Version des Modus, wobei:
Ich mache zuerst eine Gaußsche Glättung der 10 Nicht-Null-Werte ... und nehme den Argmax (Modus) dieser Verteilungen.
Danke für alle Gedanken oder Vorschläge!
***
Lösungsideen: Ein Gedanke, den ich hatte, war, weil ich mehrere verschiedene Berechnungen mit den letzten 10 Nicht-Null-Werten durchführen möchte, sollte ich zuerst eine Spalte C konstruieren, deren Einträge Arrays sind, die gleich diesen letzten 10 Nicht-Null-Werten sind ... dann I kann 3 Formeln ausführen, die mit Spalte C arbeiten, um B1 (Mittelwert), B2 (Mittelwert), B3 (geglätteter Modus) zu erzeugen.
Hier sind einige Codefragmente, die sich zum Aufbau dieser Spalte C von Arrays bewegen:
//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
DatentabelleSkripterstellungBetreff: Wie konstruiere ich eine Spalte A, deren Einträge gleich dem Mittelwert/Median/Modus der letzten 10 Nicht-Null-Einträge einer anderen Spalte B sind?Hier ist ein Anfang für Ihre erste Anfrage.Es wird ein Mittelwert für die letzten 10 Werte für Spalte A erstellt und der Mittelwert in Spalte B eingefügt
Ich habe jetzt keine Zeit, weiter daran zu arbeiten.Vielleicht später an diesem Wochenende.
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 );
);
Betreff: Wie konstruiere ich eine Spalte A, deren Einträge gleich dem Mittelwert/Median/Modus der letzten 10 Nicht-Null-Einträge einer anderen Spalte B sind?@DonMcCormack Dies würde ein gutes Herausforderungsproblem darstellen.
Ich denke, das wird funktionieren und einigermaßen effizient sein.
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
)
);
Betreff: Wie konstruiere ich eine Spalte A, deren Einträge gleich dem Mittelwert/Median/Modus der letzten 10 Nicht-Null-Einträge einer anderen Spalte B sind?Hallo,
Hier ist eine andere Möglichkeit, dies zu tun, indem eine Zwischentabelle ohne Fehlstellen verwendet wird, die eine einfachere Formel ermöglicht.
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>
Wenn die ursprüngliche Tabelle klein ist (wie Ihre ... etwa 15.000 Zeilen), funktionieren die beiden Ansätze ähnlich - der erste ist etwas schneller:

Wenn die ursprüngliche Tabelle wächst, scheinen die Skalen des Ansatzes "separate Tabelle" deutlich besser zu skalieren und laufen in etwa 1/10 der Zeit. Hier ist ein Beispiel mit 150.000 Zeilen:

Ein möglicher Deal-Breaker (??) ist, dass dieser Ansatz keine Formel in der Quelltabelle erzeugt, sodass Sie diese jedes Mal erneut ausführen müssten, wenn neue Daten angehängt werden.
Ich habe die 150K-Zeilendatei angehängt, falls Sie experimentieren möchten.
Prost,
Brady
Betreff: Wie konstruiere ich eine Spalte A, deren Einträge gleich dem Mittelwert/Median/Modus der letzten 10 Nicht-Null-Einträge einer anderen Spalte B sind?Hier sind noch ein paar Ergebnisse. Die "getrennte" Methode scheint linear zu skalieren. Die Methode der "gleichen Tabelle" scheint irgendwo nördlich von 450.000 Zeilen an eine Wand zu stoßen. Ich bin mir nicht sicher warum.


Betreff: Wie konstruiere ich eine Spalte A, deren Einträge gleich dem Mittelwert/Median/Modus der letzten 10 Nicht-Null-Einträge einer anderen Spalte B sind?Ich vermute, es ist immer noch N^2 für den Helfer=AsConstant. Das wird ein 100K-Array 400K-mal kopieren ...
edit: Vermutung bestätigt. Aber selbst wenn ich den Helfer aus der Formel herausnehme, bleibt mein Code immer noch etwa halb so schnell wie der von Brady.
Aber ... Jims Code kann optimiert werden, um schneller zu sein ...
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;Betreff: Wie konstruiere ich eine Spalte A, deren Einträge gleich dem Mittelwert/Median/Modus der letzten 10 Nicht-Null-Einträge einer anderen Spalte B sind?Vielen Dank für all eure Antworten – ich bin überwältigt!
Ich hatte keine Gelegenheit, sie im Detail zu lesen, aber ich werde mehr antworten, wenn ich das tue.
Am besten,
Jo
Betreff: Wie konstruiere ich eine Spalte A, deren Einträge gleich dem Mittelwert/Median/Modus der letzten 10 Nicht-Null-Einträge einer anderen Spalte B sind?Das ist wirklich schön - viel eleganter als mein Ansatz.
Betreff: Wie konstruiere ich eine Spalte A, deren Einträge gleich dem Mittelwert/Median/Modus der letzten 10 Nicht-Null-Einträge einer anderen Spalte B sind?Wow ... hat mir diese Übung eine Menge beigebracht.Mein ursprünglicher Code funktionierte, war aber sooooo viel langsamer als die alternativen Methoden, dass ich mir die Zeit nahm, sie zu studieren.Sehr schneller und cleverer Code.Dann @Craige_Hales stellte seinen neuesten Code zur Verfügung, der ziemlich schnell ist, aber einen Ansatz verfolgt, der dem meines ursprünglichen Codes sehr nahe kommt.@Craige_Hales Code ist viel schneller.Und der größte Unterschied liegt in meiner mangelnden Nutzung
Begin Data Update;
.....
End Data Update;
So habe ich jetzt eine große Wertschätzung für das Aufbewahren der Update-Meldungen bis zum Ende der Aktualisierung gewonnen.
Danke für den Spaß!