Ausgabe
Ich habe eine Frage, auf die ich in einem ähnlichen Zusammenhang bereits eine Antwort erhalten habe. Es gelingt mir jedoch nicht, die Lösung zu übertragen, und ich bin für jeden Hinweis dankbar, wo ich den Fehler mache.
Ich möchte den Abstand (Abstand) zwischen einer ArucoID i und der vorhergehenden ArucoID i+1 in Bewegungsrichtung für jede FrameID berechnen. Grundsätzlich ist dies die Berechnung des Abstands zwischen Werten aus zwei Spalten eines sortierten und gruppierten Datenrahmens. Dann möchte ich den gleitenden Mittelwert auch auf diese Entfernung (rolling_headway) anwenden.
Ich gehe davon aus, dass die von @jlandercy vorgeschlagene Lösung analog funktionieren sollte:
Die Daten sind:
import numpy as np
import pandas as pd
data1 = {
'ArucoID' : [910, 910, 910, 910, 910, 898, 898, 898, 898, 898, 912, 912, 912, 912, 912],
'Subtrial' : ['01', '01', '01', '01', '01', '01', '01', '01', '01', '01', '01', '01', '01', '01', '01'],
'frameID' : [1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5],
'xPos' : [10.0, 10.5, 11.0, 12.0, 13, 4.0, 5.0, 6.0, 7.0, 9.0, 1.5, 2.0, 2.5, 3.0, 4.0 ],
'yPos' : [-0.2, -0.1, -0.1, 0.0, 0.0, 0.2, 0.2, -0.1, 0.0, 0.05, -0.2, -0.1, 0.0, 0.1, 0.05],
}
data2 = {
'ArucoID' : [910, 910, 910, 910, 910, 898, 898, 898, 898, 898, 912, 912, 912, 912, 912],
'Subtrial' : ['02', '02', '02', '02', '02', '02', '02', '02', '02', '02', '02', '02', '02', '02', '02'],
'frameID' : [1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5],
'xPos' : [9.4, 9.5, 9.0, 9.0, 10, 3.0, 4.0, 5.0, 6.0, 7.0, 2.5, 3.0, 3.5, 3.5, 5.0 ],
'yPos' : [-0.2, -0.1, -0.1, 0.0, 0.0, 0.2, 0.2, -0.1, 0.0, 0.05, -0.2, -0.1, 0.0, 0.1, 0.05],
}
df_raw = pd.concat([
pd.DataFrame(data1),
pd.DataFrame(data2)
])
Mein Versuch:
- Sortieren der df nach frameID. Hier ist es wichtig, dass die ArucoID unsortiert bleibt, da die Reihenfolge nicht zwingend aufsteigend ist. Mit anderen Worten, ich möchte die Reihenfolge der ArucoIDs beibehalten.
df = df_raw.sort_values(["Subtrial", "frameID"])
- Ermittlung der verschobenen x-Position (Bewegungsrichtung ist in x-Richtung):
shifted = df.groupby(["Subtrial"]).shift(-1)
#print(shifted)
shifted = shifted.drop("frameID", axis=1).rename(columns=lambda x: x + "_")
data = pd.concat([df, shifted], axis=1)
- Berechnung des Abstands in Punkt (Rahmen):
def dX(x):
return np.sqrt(np.power(x["xPos"] - x["xPos_"], 2))
data['point_headway'] = data.apply(dX, axis=1)
- Sortieren Sie die dfs nach ArucoID und Subtrial (weil ich den gleitenden Mittelwert für die spezifische ArucoID haben möchte), wenden Sie dann den gleitenden Mittelwert an (unter der Annahme einer Fenstergröße von 3 hier).
data["rolling_headway"] = data.sort_values(["Subtrial", "ArucoID",'frameID']).groupby(["Subtrial", "ArucoID"]).rolling(3, min_periods=2).mean()["point_headway"].values
#print(data)
Es fuehrt zu:
frameID xPos yPos ... ArucoID_ point_headway rolling_headway
5 1 4.0 0.20 ... 912.0 2.5 2.750000
6 2 5.0 0.20 ... 912.0 3.0 4.166667
7 3 6.0 -0.10 ... 912.0 3.5 5.500000
8 4 7.0 0.00 ... 912.0 4.0 NaN
9 5 9.0 0.05 ... 912.0 5.0 9.500000
Was ich erwartet habe (siehe letzte Spalte)
frameID xPos yPos ... ArucoID_ point_headway expected
5 1 4.0 0.20 ... 912.0 2.5 NaN
6 2 5.0 0.20 ... 912.0 3.0 NaN
7 3 6.0 -0.10 ... 912.0 3.5 3.000000 (2.5+3.0+3.5)/3
8 4 7.0 0.00 ... 912.0 4.0 3.500000 (3.0+3.5+4.0)/3
9 5 9.0 0.05 ... 912.0 5.0 4.166667 (3.5+4.0+5.0)/3
Wo habe ich den Denkfehler? Ich glaube, ich sortiere falsch, nicht wahr?
Vielen Dank im Voraus für Ihren Rat!
Lösung
df = df_raw.sort_values(["Subtrial", "frameID"])
# I wasn't sure what your were doing here...
# absolute value was the only thing that made sense.
# I also didn't bother to make all those new columns.
df['point_headway'] = df.xPos.sub(df.groupby('Subtrial').xPos.shift(-1)).abs()
# I ignore_index here, so that the order is what you seem to expect.
df = df.sort_values(["Subtrial", "ArucoID",'frameID'], ignore_index=True)
# Your issue was here. You explicitly called `.values`,
# Probably to avoid an error. But you ended up losing your indexing,
# which was all over the place due to your sortings.
df["rolling_headway"] = (df.groupby(['Subtrial', 'ArucoID'])['point_headway']
.apply(lambda x: x.rolling(3).mean()))
# I used apply, just because it drops all the groupby key data and gives us our original index.
print(df)
Ausgabe:
ArucoID Subtrial frameID xPos yPos point_headway rolling_headway
0 898 01 1 4.0 0.20 2.5 NaN
1 898 01 2 5.0 0.20 3.0 NaN
2 898 01 3 6.0 -0.10 3.5 3.000000
3 898 01 4 7.0 0.00 4.0 3.500000
4 898 01 5 9.0 0.05 5.0 4.166667
5 910 01 1 10.0 -0.20 6.0 NaN
6 910 01 2 10.5 -0.10 5.5 NaN
7 910 01 3 11.0 -0.10 5.0 5.500000
8 910 01 4 12.0 0.00 5.0 5.166667
9 910 01 5 13.0 0.00 4.0 4.666667
10 912 01 1 1.5 -0.20 9.0 NaN
11 912 01 2 2.0 -0.10 9.0 NaN
12 912 01 3 2.5 0.00 9.5 9.166667
13 912 01 4 3.0 0.10 10.0 9.500000
14 912 01 5 4.0 0.05 NaN NaN
15 898 02 1 3.0 0.20 0.5 NaN
16 898 02 2 4.0 0.20 1.0 NaN
17 898 02 3 5.0 -0.10 1.5 1.000000
18 898 02 4 6.0 0.00 2.5 1.666667
19 898 02 5 7.0 0.05 2.0 2.000000
20 910 02 1 9.4 -0.20 6.4 NaN
21 910 02 2 9.5 -0.10 5.5 NaN
22 910 02 3 9.0 -0.10 4.0 5.300000
23 910 02 4 9.0 0.00 3.0 4.166667
24 910 02 5 10.0 0.00 3.0 3.333333
25 912 02 1 2.5 -0.20 7.0 NaN
26 912 02 2 3.0 -0.10 6.0 NaN
27 912 02 3 3.5 0.00 5.5 6.166667
28 912 02 4 3.5 0.10 6.5 6.000000
29 912 02 5 5.0 0.05 NaN NaN
Beantwortet von – BeRT2me
Antwort geprüft von – Jay B. (FixError Admin)