интервалы слияния и метки времени - PullRequest
0 голосов
/ 27 ноября 2018

У меня есть таблица, которая содержит интервалы

dfa = pd.DataFrame({'Start': [0, 101, 666], 'Stop': [100, 200, 1000]})

У меня есть другая таблица, которая содержит метки времени и значения

dfb = pd.DataFrame({'Timestamp': [102, 145, 113], 'ValueA': [1, 2, 21],
'ValueB': [1, 2, 21]})

Мне нужно создать кадр данных того же размера, что и dfa,с добавленным столбцом, который содержит результат некоторого агрегирования ValueA / ValueB, для всех строк в dfb с Timestamp, содержащимся между Start и Stop.

Такздесь, если определить мою агрегацию как

{'ValueA':[np.nanmean,np.nanmin],
'ValueB':[np.nanmax]}

, мой желаемый результат будет:

ValueA   ValueA    ValueB
nanmean  nanmin    nanmax    Start      Stop

nan      nan       nan        0          100
8        1         21         101        200
nan      nan       nan        666        1000

1 Ответ

0 голосов
/ 27 ноября 2018

Используйте merge с перекрестным соединением со вспомогательными столбцами, созданными assign:

d = {'ValueA':[np.nanmean,np.nanmin],
     'ValueB':[np.nanmax]}

df = dfa.assign(A=1).merge(dfb.assign(A=1), on='A', how='outer')

Затем выполните фильтрацию по Start и Stopи агрегировать по словарю:

df = (df[(df.Timestamp >= df.Start) & (df.Timestamp <= df.Stop)]
         .groupby(['Start','Stop']).agg(d))

Свести MultiIndex на map с join:

df.columns = df.columns.map('_'.join)
print (df)
            ValueA_nanmean  ValueA_nanmin  ValueB_nanmax
Start Stop                                              
101   200                8              1             21

И последний join до оригинала:

df = dfa.join(df, on=['Start','Stop'])
print (df)
   Start  Stop  ValueA_nanmean  ValueA_nanmin  ValueB_nanmax
0      0   100             NaN            NaN            NaN
1    101   200             8.0            1.0           21.0
2    666  1000             NaN            NaN            NaN

РЕДАКТИРОВАТЬ:

Решение с cut:

d = {'ValueA':[np.nanmean,np.nanmin],
     'ValueB':[np.nanmax]}

#if not default index create it
dfa = dfa.reset_index(drop=True)
print (dfa)
   Start  Stop
0      0   100
1    101   200
2    666  1000

#add to bins first value of Start
bins = np.insert(dfa['Stop'].values, 0, dfa.loc[0, 'Start'])
print (bins)
[   0  100  200 1000]

#binning
dfb['id'] = pd.cut(dfb['Timestamp'], bins=bins, labels = dfa.index)
print (dfb)
   Timestamp  ValueA  ValueB id
0        102       1       1  1
1        145       2       2  1
2        113      21      21  1

#aggregate and flatten
df = dfb.groupby('id').agg(d)
df.columns = df.columns.map('_'.join)

#add to dfa
df = pd.concat([dfa, df], axis=1)
print (df)
   Start  Stop  ValueA_nanmean  ValueA_nanmin  ValueB_nanmax
0      0   100             NaN            NaN            NaN
1    101   200             8.0            1.0           21.0
2    666  1000             NaN            NaN            NaN
...