我有两个由Date索引的DataFrame,在一个DataFrame上,每行每小时更改一次,它会更改(有时它会每5分钟更改一次,但有时会有不同的步骤)。
>>> print df2['value']
date
2015-10-06 09:00:00 0.612303
2015-10-06 10:00:00 0.482605
2015-10-06 11:00:00 0.604132
>>> print df1['value']
date
2015-10-06 09:05:00 0.412303
2015-10-06 09:08:00 0.112303
2015-10-06 09:28:00 0.012303
2015-10-06 10:15:00 0.000005
2015-10-06 11:00:00 0.133132
我希望小时h和h + 1之间的df1
值具有相应的df2
值。
通缉结果:
>>> print df1['value']
date
2015-10-06 09:05:00 0.612303
2015-10-06 09:08:00 0.612303
2015-10-06 09:28:00 0.612303
2015-10-06 10:15:00 0.482605
2015-10-06 11:00:00 0.604132
我怎样才能做到这一点?
答案 0 :(得分:4)
您可以使用merge_asof
为您的示例生成一个正确的值列,其中包含DatetimeIndex:
pd.merge_asof(df1.reset_index(), # see note about reset_index below
df2.reset_index(),
on='date',
tolerance=pd.Timedelta('1H'))
容差参数允许您指定合并应在有效的特定时间之后多长时间。例如,如果我们指定tolerance=pd.Timedelta('10m')
(10分钟),则不是所有值都可以合并,而是某些位置标记为NaN
。
请注意,我必须在合并之前重置两个帧的索引。我想使用left_index=True
和right_index=True
进行合并,但是当传入容差参数时,pandas拒绝允许此操作(这可能是一个错误 - 使用merge_asof
如果更改则应该更加整洁)。
答案 1 :(得分:1)
对于Pandas版本0.19.0或更高版本,请参阅ajcr's answer。
对于Pandas版本< 0.19.0:您可以将两个DataFrame与concat
合并,使用ffill
使用所需的值向前填充NaN值,然后update
df1
值:
import pandas as pd
df2 = pd.DataFrame({'value':[0.612303,0.482605,0.604132]}, index=pd.DatetimeIndex(['2015-10-06 09:00:00', '2015-10-06 10:00:00', '2015-10-06 11:00:00']))
df1 = pd.DataFrame({'value':[0.412303, 0.112303, 0.012303, 0.000005, 0.133132]}, index=pd.DatetimeIndex(['2015-10-06 09:05:00', '2015-10-06 09:08:00', '2015-10-06 09:28:00', '2015-10-06 10:15:00', '2015-10-06 11:00:00']))
df1.update(pd.concat([df1, df2], axis=1).ffill().iloc[:, 1])
print(df1)
产量
value
2015-10-06 09:05:00 0.612303
2015-10-06 09:08:00 0.612303
2015-10-06 09:28:00 0.612303
2015-10-06 10:15:00 0.482605
2015-10-06 11:00:00 0.604132
或者,您可以使用searchsorted
查找指示df1.index
适合df2.index
的位置的索引值:
import pandas as pd
df2 = pd.DataFrame({'value':[0.612303,0.482605,0.604132]}, index=pd.DatetimeIndex(['2015-10-06 09:00:00', '2015-10-06 10:00:00', '2015-10-06 11:00:00']))
df1 = pd.DataFrame({'value':[0.412303, 0.112303, 0.012303, 0.000005, 0.133132]}, index=pd.DatetimeIndex(['2015-10-06 09:05:00', '2015-10-06 09:08:00', '2015-10-06 09:28:00', '2015-10-06 10:15:00', '2015-10-06 11:00:00']))
df1['value'] = df2.iloc[df2.index.searchsorted(df1.index, side='right')-1].values
print(df1)
产量
value
2015-10-06 09:05:00 0.612303
2015-10-06 09:08:00 0.612303
2015-10-06 09:28:00 0.612303
2015-10-06 10:15:00 0.482605
2015-10-06 11:00:00 0.604132
请注意,searchsorted
假定df2.index
已按排序顺序排列。如果不是,请先使用df2 = df2.sort_index()
。
相反,pd.concat
返回DatatimeIndex已排序的DataFrame
订单,即使df1.index
和/或df2.index
未按排序顺序排列。因此,对于第一种方法,不需要调用sort_index
。
在这两种方法中,searchsorted
更快。例如,使用此设置:
import numpy as np
import pandas as pd
N = 1000
df1 = pd.DataFrame(np.random.random(N), index=pd.date_range('2000-1-1', periods=N, freq='14T'))
df2 = pd.DataFrame(np.random.random(int(N/60*14)), index=pd.date_range('2000-1-1', periods=int(N/60*14), freq='1H'))
df3, df4 = df1.copy(), df1.copy()
df3.update(pd.concat([df3, df2], axis=1).ffill().iloc[:, 1])
df4[0] = df2.iloc[df2.index.searchsorted(df4.index, side='right')-1].values
assert df3.equals(df4)
searchsorted
快了〜2.8倍:
In [88]: %timeit df3.update(pd.concat([df3, df2], axis=1).ffill().iloc[:, 1])
100 loops, best of 3: 2.13 ms per loop
In [89]: %timeit df4[0] = df2.iloc[df2.index.searchsorted(df4.index, side='right')-1].values
1000 loops, best of 3: 744 µs per loop
In [90]: len(df1), len(df2)
Out[90]: (1000, 233)
答案 2 :(得分:0)
在你的df1中创建一个新列"每小时"从它的索引 然后在这个新创建的列上简单地将df1与df2连接,以添加df2中的值。
将尽快发布代码:)
编辑:正如所承诺的,这是代码
import pandas as pd
from datetime import datetime
df1 = pd.read_csv("df1.csv",index_col="date", parse_dates=True)
df2 = pd.read_csv("df2.csv",index_col="date", parse_dates=True)
def fromTimeStampToHour(date):
datetimeObj = date.to_datetime()
hourlyObj = datetime(year=datetimeObj.year,month= datetimeObj.month, day = datetimeObj.day, hour=datetimeObj.hour)
return hourlyObj
df1["Hours"] = df1.index.map(lambda x: fromTimeStampToHour(x))
print pd.merge(left=df1, right=df2, left_on="Hours", right_index=True, suffixes=("_df1", "_df2"))