[英]Pandas Merge a Grouped-by dataframe with another dataframe for each group
我有一个像这样的数据框:
id date temperature
1 2011-09-12 12
2011-09-15 12
2011-10-13 12
2 2011-12-12 14
2011-12-24 15
我想确保每个设备ID都有每天的温度记录,如果值存在,它将从上面复制,如果它没有我将放0。
所以,我准备了另一个具有全年日期的数据框:
使用pd.DataFrame(0, index=pd.range('2011-01-01', '2011-12-12'), columns=['temperature'])
date temperature
2011-01-01 0
.
.
.
2011-12-12 0
现在,对于每个id,我想合并这个数据帧,这样我就可以获得每个id的全年条目。
我陷入了合并步骤,只是合并日期列不起作用,即
pd.merge(df1, df2, on=['date'])
给出一个空白的数据帧。
通过MultiIndex.from_product
创建MultiIndex
并通过MultiIndex
es合并:
mux = pd.MultiIndex.from_product([df.index.levels[0],
pd.date_range('2011-01-01', '2011-12-12')],
names=['id','date'])
df1 = pd.DataFrame(0, index=mux, columns=['temperature'])
df = pd.merge(df1, df, left_index=True, right_index=True, how='left')
如果想只有一个temperature
:
df = pd.merge(df1, df, left_index=True, right_index=True, how='left', suffixes=('','_'))
df['temperature'] = df.pop('temperature_').fillna(df['temperature'])
另一个想法是使用itertools.product
为2 columns
DataFrame:
from itertools import product
data = list(product(df.index.levels[0], pd.date_range('2011-01-01', '2011-12-12')))
df1 = pd.DataFrame(data, columns=['id','date'])
df = pd.merge(df1, df, left_on=['id','date'], right_index=True, how='left')
另一个想法是使用DataFrame.reindex
:
mux = pd.MultiIndex.from_product([df.index.levels[0],
pd.date_range('2011-01-01', '2011-12-12')],
names=['id','date'])
df = df.reindex(mux, fill_value=0)
作为jezrael的答案的替代方案,您还可以执行以下迭代,尤其是如果您希望保持设备ID完整:
data={"date":[pd.Timestamp('2011-09-12'), pd.Timestamp('2011-09-15'), pd.Timestamp('2011-10-13'),pd.Timestamp('2011-12-12'),pd.Timestamp('2011-12-24')],"temperature":[12,12,12,14,15],"sensor_id":[1,1,1,2,2]}
df1=pd.DataFrame(data,index=data["sensor_id"])
df2=pd.DataFrame(0, index=pd.date_range('2011-01-01', '2011-12-12'), columns=['temperature','sensor_id'])
for i,row in df1.iterrows():
df2.loc[df2.index==row["date"], ['temperature']] = row['temperature']
df2.loc[df2.index==row["date"], ['sensor_id']] = row['sensor_id']
for t in data["date"]:
print(df2[df2.index==t])
请注意,您的问题中的df2
仅转到2011-12-12
,因此最后一个print()
将返回一个空的DataFrame。 我不是故意这样做的。
此外,根据实际数据的可变性和密度,使用可能有意义:
for s in [1,2]: ## iterate over device ids
ma=(df['sensor_id']==s)
df.loc[ma]=df.loc[ma].fillna(method='ffill') # fill forward
因此,不完整的时间序列将被最后测量的温度值填充(向前)。 当然,取决于数据的质量, df.resample()
可能更有意义。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.