2017-06-20 9 views
2

異なる列の値に基づいて行の値を減算する必要があります。私はcol3の値に基づいてcol1col2の組み合わせでの平均時間差を計算する必要が最適な方法Pythonの列値に基づいて行を減算する

Id | col1 | col2 | col3 | 
1 | 2016-01-02 | 7:00:00 | Yes | 
1 | 2016-01-02 | 7:05:00 | No | 
1 | 2016-01-02 | 7:10:00 | Yes | 
1 | 2016-01-02 | 8:00:00 | No | 
2 | 2016-01-02 | 7:10:00 | Yes | 
2 | 2016-01-02 | 7:50:00 | No | 
2 | 2016-01-02 | 9:00:00 | No | 
2 | 2016-01-02 | 9:10:00 | No | 
2 | 2016-01-02 | 9:15:00 | No | 
3 | 2016-01-02 | 6:05:00 | Yes | 
3 | 2016-01-02 | 6:10:00 | Yes | 
3 | 2016-01-02 | 6:20:00 | Yes | 
3 | 2016-01-02 | 6:45:00 | No | 

:私のデータフレームは、このようになります。ルールは以下の通りです:

col3Yesは何がある時はいつでも私がこれまで行ったことの簡易版は、データフレーム内のすべての値とをループにあるrow-next row

これを行います:

for i in range(len(df)): 
    if df['col3'][i] == 'Yes': 
     date1 = datetime.combine(df['col1'][i], df['col2'][i]) 
     date2 = datetime.combine(df['col1'][i+1], df['col2'][i+1]) 
     dict[df['Id'][i]] = date1-date2 

変数dictは、それぞれ異なるIdの結果を保持しているだけの辞書です。

私は6MM以上の行を持っているので、ループは完了するまでに多くの時間がかかります。だから、誰かがより効率的で洗練されたソリューションを考え出すことができるのだろうかと思いました。

ありがとうございます!

答えて

1

私はあなたが使用することができると思う:

#datetime column - add time to dates 
df['datetime'] = pd.to_datetime(df['col1']) + pd.to_timedelta(df['col2']) 
#get difference of all values, filter by multiple mask only if `Yes` 
#convert to ns for numeric for aggregate 
df['dif']=df['datetime'].diff(-1).mul(df['col3'] == 'Yes').fillna(0).values.astype(np.int64) 
print (df) 
    Id  col1  col2 col3   datetime   dif 
0 1 2016-01-02 7:00:00 Yes 2016-01-02 07:00:00 -300000000000 
1 1 2016-01-02 7:05:00 No 2016-01-02 07:05:00    0 
2 1 2016-01-02 7:10:00 Yes 2016-01-02 07:10:00 -3000000000000 
3 1 2016-01-02 8:00:00 No 2016-01-02 08:00:00    0 
4 2 2016-01-02 7:10:00 Yes 2016-01-02 07:10:00 -2400000000000 
5 2 2016-01-02 7:50:00 No 2016-01-02 07:50:00    0 
6 2 2016-01-02 9:00:00 No 2016-01-02 09:00:00    0 
7 2 2016-01-02 9:10:00 No 2016-01-02 09:10:00    0 
8 2 2016-01-02 9:15:00 No 2016-01-02 09:15:00    0 
9 3 2016-01-02 6:05:00 Yes 2016-01-02 06:05:00 -300000000000 
10 3 2016-01-02 6:10:00 Yes 2016-01-02 06:10:00 -600000000000 
11 3 2016-01-02 6:20:00 Yes 2016-01-02 06:20:00 -1500000000000 
12 3 2016-01-02 6:45:00 No 2016-01-02 06:45:00    0 

d = pd.to_timedelta(df.groupby('Id')['dif'].mean()).to_dict() 
print (d) 
{1: Timedelta('-1 days +23:46:15'), 
2: Timedelta('-1 days +23:52:00'), 
3: Timedelta('-1 days +23:50:00')} 

と同じである何:

datetime = pd.to_datetime(df['col1']) + pd.to_timedelta(df['col2']) 
diff = datetime.diff(-1).mul(df['col3'] == 'Yes').fillna(0).values.astype(np.int64) 
d = pd.to_timedelta(pd.Series(diff, index=df.index).groupby(df['Id']).mean()).to_dict() 
print (d) 
{1: Timedelta('-1 days +23:46:15'), 
2: Timedelta('-1 days +23:52:00'), 
3: Timedelta('-1 days +23:50:00')} 

しかし、もし削除負のはtimedeltaための絶対値がnumpy.absを追加必要があります。

df['datetime'] = pd.to_datetime(df['col1']) + pd.to_timedelta(df['col2']) 
df['dif'] = np.abs(df['datetime'].diff(-1) 
           .mul(df['col3'] == 'Yes') 
           .fillna(0) 
           .values 
           .astype(np.int64)) 
print (df) 
    Id  col1  col2 col3   datetime   dif 
0 1 2016-01-02 7:00:00 Yes 2016-01-02 07:00:00 300000000000 
1 1 2016-01-02 7:05:00 No 2016-01-02 07:05:00    0 
2 1 2016-01-02 7:10:00 Yes 2016-01-02 07:10:00 3000000000000 
3 1 2016-01-02 8:00:00 No 2016-01-02 08:00:00    0 
4 2 2016-01-02 7:10:00 Yes 2016-01-02 07:10:00 2400000000000 
5 2 2016-01-02 7:50:00 No 2016-01-02 07:50:00    0 
6 2 2016-01-02 9:00:00 No 2016-01-02 09:00:00    0 
7 2 2016-01-02 9:10:00 No 2016-01-02 09:10:00    0 
8 2 2016-01-02 9:15:00 No 2016-01-02 09:15:00    0 
9 3 2016-01-02 6:05:00 Yes 2016-01-02 06:05:00 300000000000 
10 3 2016-01-02 6:10:00 Yes 2016-01-02 06:10:00 600000000000 
11 3 2016-01-02 6:20:00 Yes 2016-01-02 06:20:00 1500000000000 
12 3 2016-01-02 6:45:00 No 2016-01-02 06:45:00    0 

d = pd.to_timedelta(df.groupby('Id')['dif'].mean()).to_dict() 
print (d) 
{1: Timedelta('0 days 00:13:45'), 
2: Timedelta('0 days 00:08:00'), 
3: Timedelta('0 days 00:10:00')} 
+0

はい、非常によりクリーンで速い。 mul関数を説明してください。私はドキュメンテーションを見ていますが、それが何をしているのか理解できないようです。 https://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.mul.html –

+0

['Series.mul'](http://pandas.pydata.org/pandas)をチェックすることができます。 -docs/stable/generated/pandas.Series.mul.html)、 'Yes'の場合は1に、' Yes'の場合は '0'に単純に倍数になります。 – jezrael

関連する問題