2016-10-17 53 views
2

マージは特定の範囲内の日付/時刻を条件とする別のデータフレームをマージしたいと思います。pandas:時間範囲で条件付きのマージ

たとえば、次の2つのデータフレームがあるとします。

import pandas as pd 
import datetime 

# Create main data frame. 
data = pd.DataFrame() 
time_seq1 = pd.DataFrame(pd.date_range('1/1/2016', periods=3, freq='H')) 
time_seq2 = pd.DataFrame(pd.date_range('1/2/2016', periods=3, freq='H')) 
data = data.append(time_seq1, ignore_index=True) 
data = data.append(time_seq1, ignore_index=True) 
data = data.append(time_seq1, ignore_index=True) 
data = data.append(time_seq2, ignore_index=True) 
data['myID'] = ['001','001','001','002','002','002','003','003','003','004','004','004'] 
data.columns = ['Timestamp', 'myID'] 

# Create second data frame. 
data2 = pd.DataFrame() 
data2['time'] = [pd.to_datetime('1/1/2016 12:06 AM'), pd.to_datetime('1/1/2016 1:34 AM'), pd.to_datetime('1/2/2016 12:25 AM')] 
data2['myID'] = ['002', '003', '004'] 
data2['specialID'] = ['foo_0', 'foo_1', 'foo_2'] 

# Show data frames. 
data 
      Timestamp myID 
0 2016-01-01 00:00:00 001 
1 2016-01-01 01:00:00 001 
2 2016-01-01 02:00:00 001 
3 2016-01-01 00:00:00 002 
4 2016-01-01 01:00:00 002 
5 2016-01-01 02:00:00 002 
6 2016-01-01 00:00:00 003 
7 2016-01-01 01:00:00 003 
8 2016-01-01 02:00:00 003 
9 2016-01-02 00:00:00 004 
10 2016-01-02 01:00:00 004 
11 2016-01-02 02:00:00 004 

data2 
       time myID specialID 
0 2016-01-01 00:06:00 002  foo_0 
1 2016-01-01 01:34:00 003  foo_1 
2 2016-01-02 00:25:00 004  foo_2 

次の出力を作成します。特に

# Desired output. 
      Timestamp myID special_ID 
0 2016-01-01 00:00:00 001  NaN 
1 2016-01-01 01:00:00 001  NaN 
2 2016-01-01 02:00:00 001  NaN 
3 2016-01-01 00:00:00 002  NaN 
4 2016-01-01 01:00:00 002  foo_0 
5 2016-01-01 02:00:00 002  NaN 
6 2016-01-01 00:00:00 003  NaN 
7 2016-01-01 01:00:00 003  NaN 
8 2016-01-01 02:00:00 003  foo_1 
9 2016-01-02 00:00:00 004  NaN 
10 2016-01-02 01:00:00 004  foo_2 
11 2016-01-02 02:00:00 004  NaN 

、私はTimestamptimeの値の後に発生する最初の時間になるようにdataspecial_IDをマージしたいです。すなわちmyID = 002を含む行のうち、直ちに2016-01-01 00:06:00以下dataにおける次回(special_ID = foo_0time)であるので、例えば、foo_0myID = 0022016-01-01 01:00:00に対応する行であろう。

注:Timestampdataのインデックスではなく、timedata2のインデックスではありません。他の関連記事のほとんどは、datetimeオブジェクトをデータフレームのインデックスとして使用することに依存しているようです。

答えて

8

あなたは、ほとんどの作業を行うには、パンダ0.19で新しく追加された、​​を使用することができます。その後、二次マッチを削除するlocduplicatedを兼ね備え:

# Data needs to be sorted for merge_asof. 
data = data.sort_values(by='Timestamp') 

# Perform the merge_asof. 
df = pd.merge_asof(data, data2, left_on='Timestamp', right_on='time', by='myID').drop('time', axis=1) 

# Make the additional matches null. 
df.loc[df['specialID'].duplicated(), 'specialID'] = np.nan 

# Get the original ordering. 
df = df.set_index(data.index).sort_index() 

結果の出力:

   Timestamp myID specialID 
0 2016-01-01 00:00:00 001  NaN 
1 2016-01-01 01:00:00 001  NaN 
2 2016-01-01 02:00:00 001  NaN 
3 2016-01-01 00:00:00 002  NaN 
4 2016-01-01 01:00:00 002  foo_0 
5 2016-01-01 02:00:00 002  NaN 
6 2016-01-01 00:00:00 003  NaN 
7 2016-01-01 01:00:00 003  NaN 
8 2016-01-01 02:00:00 003  foo_1 
9 2016-01-02 00:00:00 004  NaN 
10 2016-01-02 01:00:00 004  foo_2 
11 2016-01-02 02:00:00 004  NaN 
+1

完璧に!私はちょうどこれに取り組んでいた、今私はする必要はありません。 :-) – piRSquared

+0

あなたは何らかのバグがあり、データのタイムスタンプを変更しました – Oren

+0

@Oren:いいえ、私の出力はちょっと違った方法でソートされています。 – root

1

あまり美しくないが、私はそれがうまくいくと思う。

data['specialID'] = None 
foolist = list(data2['myID']) 
for i in data.index: 
    if data.myID[i] in foolist: 
     if data.Timestamp[i]> list(data2[data2['myID'] == data.myID[i]].time)[0]: 
      data['specialID'][i] = list(data2[data2['myID'] == data.myID[i]].specialID)[0] 
      foolist.remove(list(data2[data2['myID'] == data.myID[i]].myID)[0]) 

In [95]: data 
Out[95]: 
      Timestamp myID specialID 
0 2016-01-01 00:00:00 001  None 
1 2016-01-01 01:00:00 001  None 
2 2016-01-01 02:00:00 001  None 
3 2016-01-01 00:00:00 002  None 
4 2016-01-01 01:00:00 002  foo_0 
5 2016-01-01 02:00:00 002  None 
6 2016-01-01 00:00:00 003  None 
7 2016-01-01 01:00:00 003  None 
8 2016-01-01 02:00:00 003  foo_1 
9 2016-01-02 00:00:00 004  None 
10 2016-01-02 01:00:00 004  foo_2 
11 2016-01-02 02:00:00 004  None 
関連する問題