首页 > 解决方案 > 在以重复日期为索引的数据帧上使用 combine_first

问题描述

我有两个数据框,其中包含同一数据框中不同位置的不同日期的气象数据,这是我的数据的更简单版本,它重现了该问题:

df = pd.DataFrame(np.random.randint(0,30,size=(10, 4)), columns=(['Temp', 'Precip', 'Wind', 'Pressure']))
df1 = pd.DataFrame(np.random.randint(0,30,size=(10, 4)), columns=(['Temp', 'Precip', 'Wind', 'Pressure']))

df['Location'] =[2,2,3,3,4,4,5,5,6,6]
df1['Location'] =[2,2,3,3,4,4,5,5,6,6]

这些在 2020 年 5 月 18 日和 19 日为 df 编制索引,5 月 19 日和 20 日为 df1 编制索引,如下所示:

df.index = ["2020-05-18 12:00:00","2020-05-19 12:00:00","2020-05-18 12:00:00","2020-05-19 12:00:00","2020-05-18 12:00:00","2020-05-19 12:00:00","2020-05-18 12:00:00","2020-05-19 12:00:00","2020-05-18 12:00:00","2020-05-19 12:00:00"]
df1.index = ["2020-05-19 12:00:00", "2020-05-20 12:00:00", "2020-05-19 12:00:00", "2020-05-20 12:00:00", "2020-05-19 12:00:00", "2020-05-20 12:00:00", "2020-05-19 12:00:00", "2020-05-20 12:00:00", "2020-05-19 12:00:00", "2020-05-20 12:00:00"]

df.index = pd.to_datetime(df.index)
df1.index = pd.to_datetime(df1.index)

数据框的结构方式意味着每个Location点在每个数据框中都有 2 天的数据。df 中的第 18 和 19 号,df1 中的第 19 和 20 号。看起来像这样:

在此处输入图像描述 在此处输入图像描述

我想将这两个数据帧组合到 df3 中,其中我有每个位置点的第 18、19 和 20 个值,其中第 18 个来自 df,第 19 个和第 20 个来自 df1。即 df1 在同一日期覆盖每个位置的 df,然后附加所有后续日期的数据,以生成如下所示的内容:

在此处输入图像描述

实际上,我在很多天里有数百个位置,所以这需要根据索引来工作(我认为)。

我试过这样的pd.combine_first方法:

df.combine_first(df1)

但是(由于索引中的重复日期)这会产生一个数据框,其中的单元格比我想要的多得多——总共应该有 15 个,而且还有更多。

在此处输入图像描述

我认为这是由于索引的原因,因为当我尝试一个仅针对一个位置的更简单日期的示例时,它可以正常工作 - 但我无法弄清楚如何在同一数据框中具有多个位置的数据上执行此操作。我真的很感激一些帮助!

编辑:下面标记的答案确实解决了这个问题,但是现在当我想添加与索引长度不匹配的新数据时:

import pandas as pd
import numpy as np

df = pd.DataFrame(np.random.randint(0,30,size=(10, 4)), columns=(['Temp', 'Precip', 'Wind', 'Pressure']))
df1 = pd.DataFrame(np.random.randint(0,30,size=(11, 4)), columns=(['Temp', 'Precip', 'Wind', 'Pressure']))

df['Location'] =[2,2,3,3,4,4,5,5,6,6]
df1['Location'] =[1,2,2,3,3,4,4,5,5,6,6]

df.index = ["2020-05-18 12:00:00","2020-05-19 12:00:00","2020-05-18 12:00:00","2020-05-19 12:00:00","2020-05-18 12:00:00","2020-05-19 12:00:00","2020-05-18 12:00:00","2020-05-19 12:00:00","2020-05-18 12:00:00","2020-05-19 12:00:00"]
df1.index = ["2020-05-19 12:00:00", "2020-05-20 12:00:00", "2020-05-19 12:00:00", "2020-05-20 12:00:00", "2020-05-19 12:00:00", "2020-05-20 12:00:00", "2020-05-19 12:00:00", "2020-05-20 12:00:00", "2020-05-19 12:00:00", "2020-05-20 12:00:00", "2020-05-19 12:00:00"]

df.index = pd.to_datetime(df.index)
df1.index = pd.to_datetime(df1.index)

df1 

在此处输入图像描述

所以我现在有另一个值为 1 的位置,我想将此位置添加到 df,同时使用 df1 的值更新值。当我使用以下代码时:

df = df.set_index(df.groupby(level=0).cumcount(), append=True)
df1 = df1.set_index(df1.groupby(level=0).cumcount(), append=True)

df = df.combine_first(df1).sort_index(level=[1,0]).reset_index(level=1, drop=True)
print (df) 

在此处输入图像描述

它使用 df2 中的值更新 df,但会删除新位置。有没有办法解决?

标签: pythonpandasdataframe

解决方案


df3 = pd.concat([df,df1]).reset_index()
df3 = df3.drop_duplicates(subset=["index","Location"], keep="last")
df3 = df3.set_index("index").sort_index().sort_values(by="Location")

In [29]: df3
Out[29]: 
             

                     Temp  Precip  Wind  Pressure  Location
index                                                      
2020-05-18 12:00:00     9      13    17        27         2
2020-05-19 12:00:00    23      27    22         0         2
2020-05-20 12:00:00    21      22     0         5         2
2020-05-18 12:00:00    22      27    19        13         3
2020-05-19 12:00:00     4      29    21         0         3
2020-05-20 12:00:00    12      28    11        25         3
2020-05-18 12:00:00    29       8    21        20         4
2020-05-19 12:00:00    10       3    15        25         4
2020-05-20 12:00:00    23       2    14         5         4
2020-05-18 12:00:00    11      19    17        17         5
2020-05-19 12:00:00    13       1    12         7         5
2020-05-20 12:00:00     4      18    25        19         5
2020-05-18 12:00:00     3      21    16        18         6
2020-05-19 12:00:00    16      12    11        12         6
2020-05-20 12:00:00    27      19    13        19         6
    
In [30]: df3.shape
Out[30]: (15, 5)

推荐阅读