
前提・実現したいこと
Pandas.Dataframeで前の行の値を使って、行の値を変更したい
発生している問題・エラーメッセージ
以下のようなPandas.Dataframeのデータがあります。
各行はそのTimeの時点におけるx,y,zの位置を表しています。(Timeはmsec,xyzはmm)
Time x y z
0      0  1950.385254 -114.936646  845.404541
1    504  1950.385254 -114.936676  845.404419
2   1832  1950.385376 -114.936737  845.404541
3   1976  1950.389038 -114.934784  845.401611
4   1984  1950.414795 -114.921631  845.382813
5   1992  1950.484375 -114.885681  845.331421
6   2000  1950.619995 -114.815666  845.231262
7   2008  1950.843750 -114.700241  845.066101
8   2016  1951.177246 -114.528023  844.820007
9   2024  1951.642944 -114.287712  844.475952
10  2032  1952.261841 -113.967934  844.018433
11  2040  1953.056641 -113.557175  843.430725
12  2048  1954.048828 -113.044235  842.696533
13  2056  1955.259888 -112.417793  841.799194
14  2064  1956.711426 -111.666199  840.722046
15  2072  1958.424561 -110.778175  839.448792
16  2080  1960.421387 -109.742630  837.962463
17  2088  1962.721436 -108.547462  836.246277
18  2096  1965.346558 -107.182030  834.282959
19  2104  1968.317383 -105.634575  832.055420
20  2112  1971.652832 -103.893509  829.545898
21  2120  1975.370239 -101.949677  826.739685
これをうまいこと処理して、前の行との
時間の差分
位置の差分((x0-x1) ** 2 + (y0-y1) ** 2 + (z0-z1) ** 2 ) ** 0.5
位置の差分 / 時間の差分を求めたいです。
サンプルのソースコード
Python
1import pandas as pd 2 3def length(pos1,pos2): 4 ans = ((pos1.x - pos2.x) **2 + (pos1.y - pos2.y) **2 + (pos1.z - pos2.z) **2)** 0.5 5 return ans 6 7df = pd.read_excel('test2.xlsx') 8lastvar = 0 9df['df_time'] = 0 10df['len'] = 0.0 11df['spd'] = 0.0 12 13for item in df.itertuples(): 14 if (hasattr(lastvar, 'Time')): 15 diff = item.Time - lastvar.Time 16 len = length(item,lastvar) 17 df.at[item.Index, 'df_time'] = diff 18 df.at[item.Index, 'len'] = len 19 df.at[item.Index, 'spd'] = len / diff * 1000 20 21 lastvar = item 22print(df)
結果
Time x y z df_time len spd
0      0  1950.385254 -114.936646  845.404541        0  0.000000    0.000000
1    504  1950.385254 -114.936676  845.404419      504  0.000126    0.000249
2   1832  1950.385376 -114.936737  845.404541     1328  0.000183    0.000138
3   1976  1950.389038 -114.934784  845.401611      144  0.005080    0.035280
4   1984  1950.414795 -114.921631  845.382813        8  0.034493    4.311665
5   1992  1950.484375 -114.885681  845.331421        8  0.093675   11.709316
6   2000  1950.619995 -114.815666  845.231262        8  0.182556   22.819506
7   2008  1950.843750 -114.700241  845.066101        8  0.301110   37.638782
8   2016  1951.177246 -114.528023  844.820007        8  0.448822   56.102707
9   2024  1951.642944 -114.287712  844.475952        8  0.626895   78.361925
10  2032  1952.261841 -113.967934  844.018433        8  0.833436  104.179465
11  2040  1953.056641 -113.557175  843.430725        8  1.070435  133.804352
12  2048  1954.048828 -113.044235  842.696533        8  1.336630  167.078779
13  2056  1955.259888 -112.417793  841.799194        8  1.632272  204.034050
14  2064  1956.711426 -111.666199  840.722046        8  1.957576  244.697004
15  2072  1958.424561 -110.778175  839.448792        8  2.311838  288.979722
16  2080  1960.421387 -109.742630  837.962463        8  2.696079  337.009862
17  2088  1962.721436 -108.547462  836.246277        8  3.108689  388.586106
18  2096  1965.346558 -107.182030  834.282959        8  3.551097  443.887085
19  2104  1968.317383 -105.634575  832.055420        8  4.022729  502.841118
20  2112  1971.652832 -103.893509  829.545898        8  4.522635  565.329433
21  2120  1975.370239 -101.949677  826.739685        8  5.047022  630.877725
試したこと
添付のコードのように、For文でかけるといえばかけるのですが、なんだかしっくり来ないというか、
スマートでないですし、前の値をループで保存しているので、並列化等ができないと思っています。
このコードをスマートに書き換えていただけないでしょうか?
Python初めて2日程度なので、Pythonらしく直していただいて構いません。
改良後のソースコード
lehshellさんから改良案を頂き、そのあたりで自分で調べた結果もふまえて書き換えたコードを以下においておきます。
shiftメソッドの他に、diffでもできるみたいです。
Python
1import pandas as pd 2 3def length(pos1,pos2): 4 ans = ((pos1.x - pos2.x) **2 + (pos1.y - pos2.y) **2 + (pos1.z - pos2.z) **2)** 0.5 5 return ans 6 7def length2(diffx,diffy,diffz): 8 ans = (diffx ** 2 + diffy ** 2 + diffz ** 2) ** 0.5 9 return ans 10 11def method1(): #改良前 12 df = pd.read_excel('test2.xlsx') 13 lastvar = 0 14 df['df_time'] = 0 15 df['len'] = 0.0 16 df['spd'] = 0.0 17 18 for item in df.itertuples(): 19 if (hasattr(lastvar, 'Time')): 20 diff = item.Time - lastvar.Time 21 len = length(item,lastvar) 22 df.at[item.Index, 'df_time'] = diff 23 df.at[item.Index, 'len'] = len 24 df.at[item.Index, 'spd'] = len / diff * 1000 25 lastvar = item 26 print(df) 27 28def method2(): #改良案1 29 df = pd.read_excel('test2.xlsx') 30 df['df_time'] = (df['Time'] - df['Time'].shift(1)).fillna(0) 31 df['len'] = length(df, df.shift(1)).fillna(0) 32 df['spd'] = (df['len'] / df['df_time'] * 1000).fillna(0) 33 print(df) 34 35def method3(): #改良案2 36 df = pd.read_excel('test2.xlsx') 37 df['df_time'] = df['Time'].diff().fillna(0) 38 df['len'] = length2(df["x"].diff(),df["y"].diff(),df["z"].diff()).fillna(0) 39 df['spd'] = (df['len'] / df['df_time'] * 1000).fillna(0) 40 print(df) 41 42 43method1() 44method2() 45method3()


回答1件
あなたの回答
tips
プレビュー


