ゼロに達するたびに一意の値を個別に割り当てたいデータセットがあります。
私が思いついたコードは遅いようで、もっと速い方法があるに違いないと思います。
import time
import pandas as pd
import numpy as np
#--------------------------------
# DEBUG TEST DATASET
#--------------------------------
#Create random test data
series_random = np.random.randint(low=1, high=10, size=(10000,1))
#Insert zeros at known points (this should result in six motion IDs)
series_random[[5,6,7,15,100,2000,5000]] = 0
#Create data frame from test series
df = pd.DataFrame(series_random, columns=['Speed'])
#--------------------------------
#Elaped time counter
Elapsed_ms = time.time()
#Set Motion ID variable
Motion_ID = 0
#Create series with Motion IDs
df.loc[:,'Motion ID'] = 0
#Iterate through each row of df
for i in range(df.index.min()+1, df.index.max()+1):
#Set Motion ID to latest value
df.loc[i, 'Motion ID'] = Motion_ID
#If previous speed was zero and current speed is >0, then new motion detected
if df.loc[i-1, 'Speed'] == 0 and df.loc[i, 'Speed'] > 0:
Motion_ID += 1
df.loc[i, 'Motion ID'] = Motion_ID
#Include first zero value in new Motion ID (for plotting purposes)
df.loc[i-1, 'Motion ID'] = Motion_ID
Elapsed_ms = int((time.time() - Elapsed_ms) * 1000)
print('Result: {} records checked, {} unique trips identified in {} ms'.format(len(df.index),df['Motion ID'].nunique(),Elapsed_ms))
上記のコードからの出力は次のとおりです。
結果:10000レコードがチェックされ、6879ミリ秒で6つの一意のトリップが識別されました
私の実際のデータセットははるかに大きくなるので、この小さな例でも、単純な操作のように見えるのに非常に長い時間がかかったことに驚いています。
ブール配列と式を使用して、ループなしでnumpyのロジックを表現できます。
def get_motion_id(speed):
mask = np.zeros(speed.size, dtype=bool)
# mask[i] == True if Speed[i - 1] == 0 and Speed[i] > 0
mask[1:] = speed[:-1] == 0
mask &= speed > 0
# Taking the cumsum increases the motion_id by one where mask is True
motion_id = mask.astype(int).cumsum()
# Carry over beginning of a motion to the preceding step with Speed == 0
motion_id[:-1] = motion_id[1:]
return motion_id
# small demo example
df = pd.DataFrame({'Speed': [3, 0, 1, 2, 0, 1]})
df['Motion_ID'] = get_motion_id(df['Speed'])
print(df)
Speed Motion_ID
0 3 0
1 0 1
2 1 1
3 2 1
4 0 2
5 1 2
10,000行の例では、約800のスピードアップが見られます。
%time df['Motion_ID'] = get_motion_id(df['Speed'])
CPU times: user 5.26 ms, sys: 3.18 ms, total: 8.43 ms
Wall time: 8.01 ms
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加