【问题标题】:merging intervals and timestamps dataframes合并间隔和时间戳数据帧
【发布时间】:2019-04-28 21:34:46
【问题描述】:

我有一个包含间隔的表格

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 的所有行在StartStop 之间。

所以在这里如果将我的聚合定义为

{'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

【问题讨论】:

    标签: python pandas dataframe aggregation


    【解决方案1】:

    使用mergeassign 创建的辅助列交叉连接:

    d = {'ValueA':[np.nanmean,np.nanmin],
         'ValueB':[np.nanmax]}
    
    df = dfa.assign(A=1).merge(dfb.assign(A=1), on='A', how='outer')
    

    然后按StartStop过滤并按字典聚合:

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

    通过mapjoin 展平MultiIndex:

    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
    

    【讨论】:

    • 虽然这解决了问题,但无论如何我都会批准答案:我遇到了性能问题,因为外部连接产生了数百万行。有任何提高性能的提示吗?
    • @00__00__00 - 添加了剪切解决方案。
    猜你喜欢
    • 2019-06-22
    • 2021-01-09
    • 2020-11-18
    • 2019-06-23
    • 2019-10-31
    • 2021-06-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多