如何将列时间值在一定范围内且不是日期时间或时间戳记对象的两个数据帧合并在一起?

时间:2019-07-16 21:14:16

标签: python-3.x pandas

我有两个数据框,如下所示:

     time browncarbon blackcarbon
 181.7335    0.105270         NaN
 181.3809    0.166545    0.001217
 181.6197    0.071581         NaN

 422 rows x 3 columns

   start       end    toc 
179.9989  180.0002  155.0
180.0002  180.0016  152.0
180.0016  180.0030  151.0

1364 rows x 3 columns

第一个数据帧有一个时间列,该列每四分钟显示一次。第二个数据帧具有两个每两分钟间隔的时间列。这两个时间列都不同时开始和结束。但是,它们包含当天收集的数据。我如何制作另一个包含以下内容的数据框:

time browncarbon blackcarbon toc

422 rows X 4 columns

关于堆栈溢出有一个相关的答案,但是,仅当时间列是datetime或timestamp对象时才适用。链接为:How to join two dataframes for which column values are within a certain range?

附录1:封装到时间行之一中的多个开始行和结束行也应与一个toc行相对应,就像现在一样,但是,它应该是多个toc行的平均值,即目前情况并非如此。

附录2:Merging two pandas dataframes with complex conditions

4 个答案:

答案 0 :(得分:0)

我们创建了一个人工键列来进行outer merge来获取笛卡尔积(行之间的所有匹配项)。然后,我们用.query过滤时间在范围之间的所有行。

注释:我编辑了一行的值,以便我们可以进行匹配(请参见底部示例数据帧中的第0行)

df1.assign(key=1).merge(df2.assign(key=1), on='key', how='outer')\
   .query('(time >= start) & (time <= end)')\
   .drop(['key', 'start', 'end'], axis=1)

输出

       time  browncarbon  blackcarbon    toc
1  180.0008      0.10527          NaN  152.0

使用的示例数据框:

df1

       time  browncarbon  blackcarbon
0  180.0008     0.105270          NaN
1  181.3809     0.166545     0.001217
2  181.6197     0.071581          NaN

df2

      start       end    toc
0  179.9989  180.0002  155.0
1  180.0002  180.0016  152.0
2  180.0016  180.0030  151.0

答案 1 :(得分:0)

由于开始和结束间隔是互斥的,因此我们可以在df2中创建新列,使其包含floor(start)和floor(end)范围内的所有整数值。稍后,在df1中添加另一列作为floor(time),然后在df1和df2上进行左外部联接。我认为应该这样做,除非您可能需要删除nan值和多余的列。如果您将csv文件发送给我,我也许可以向您发送脚本。希望我回答了你的问题。

答案 2 :(得分:0)

您的第二个数据帧太短,因此不会反映有意义的合并。所以我做了一点修改:

df2 = pd.DataFrame({'start': [179.9989, 180.0002, 180.0016, 181.3, 181.5, 181.7],
 'end': [180.0002, 180.0016, 180.003, 181.5, 185.7, 181.8],
 'toc': [155.0, 152.0, 151.0, 150.0, 149.0, 148.0]})

df1['Rank'] = np.arange(len(df1))

new_df = pd.merge_asof(df1.sort_values('time'), df2,
          left_on='time',
          right_on='start')

给您

       time  browncarbon  blackcarbon  Rank  start    end    toc
0  181.3809     0.166545     0.001217     1  181.3  181.5  150.0
1  181.6197     0.071581          NaN     2  181.5  185.7  149.0
2  181.7335     0.105270          NaN     0  181.7  181.8  148.0

,您可以在sort_values上添加多余的列和Rank。例如:

new_df.sort_values('Rank').drop(['Rank','start','end'], axis=1)

给予:

       time  browncarbon  blackcarbon    toc
2  181.7335     0.105270          NaN  148.0
0  181.3809     0.166545     0.001217  150.0
1  181.6197     0.071581          NaN  149.0

答案 3 :(得分:0)

也许您可以将列转换为时间戳,然后在您链接的其他问题中使用答案

from pandas import Timestamp
from dateutil.relativedelta import relativedelta as rd

def to_timestamp(x):
    return Timestamp(2000, 1, 1) + rd(days=x)

df['start_time'] = df.start.apply(to_timestamp)
df['end_time'] = df.end.apply(to_timestamp)