熊猫将分组数据框与每个组的另一个数据框合并

时间:2019-04-17 09:02:22

标签: python pandas pandas-groupby

我有一个datframe,如:

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'])

给出一个空白的数据框。

2 个答案:

答案 0 :(得分:0)

MultiIndex.from_product创建MultiIndex并由两个MultiIndex合并:

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'])

另一个想法是对2 columns DataFrame使用itertools.product

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)

答案 1 :(得分:0)

作为jezrael's answer的替代方法,您还可以执行以下迭代,特别是如果您希望保持设备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()可能更有意义。