using combine_first on dataframe with repeated dates as index

Viewed 266

I have two dataframes containing meteorological data for different dates at different locations within the same dataframe, here's a simpler version of my data which reproduces the issue:

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]

These are indexed by the 18th and 19th of May 2020 for df, and the 19th and 20th of May for df1 like so:

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)

The way the dataframes are structured means each Location point has 2 days of data in each dataframe. The 18th and 19th in df, and the 19th and 20th in df1. The look like this:

enter image description here enter image description here

I want to combine these two dataframes into df3 where I have values for the 18th, 19th and 20th for each location point, where 18th comes from df, and 19th and 20th comes from df1. i.e. df1 overwrites df for each location on the same date, then appends the data for all following dates, to produce something that looks like this:

enter image description here

In reality I have hundreds of locations over many days, so this will need to work based on the index (I think).

I have tried the pd.combine_first method like so:

df.combine_first(df1)

but (because of the repeated dates in the index) this produces a dataframe with many more cells than I want - there should be 15 in total and there are many more.

enter image description here

I think this is due to the index because when I tried an example with simpler dates for just one location it works fine - but I can't figure out how to do it on my data which has multiple locations within the same dataframe. I'd really appreciate some help!

EDIT: the answer marked below does solve this issue, but now when I want to add new data which doesn't match the index length like so:

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 

enter image description here

So I now have another location with the value 1, I want to add this location to df along with updating the values with those of df1. When I use the following code:

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) 

enter image description here

It updates df with the values from df2, but it removes the new location. Is there any way around this?

2 Answers
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)

Here is problem with duplicates, so combine_first create default outer join. Solution is add helper level in MultiIndex for unique index values and last sorting with remove helper level:

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)
                     Temp  Precip  Wind  Pressure  Location
2020-05-18 12:00:00  24.0     3.0   5.0      28.0       2.0
2020-05-19 12:00:00   8.0    21.0   2.0       6.0       2.0
2020-05-20 12:00:00  10.0    12.0   4.0      15.0       2.0
2020-05-18 12:00:00  25.0     4.0   6.0      14.0       3.0
2020-05-19 12:00:00  19.0     8.0  13.0      14.0       3.0
2020-05-20 12:00:00   5.0     5.0  13.0       1.0       3.0
2020-05-18 12:00:00   6.0    27.0  16.0      15.0       4.0
2020-05-19 12:00:00  24.0     3.0  24.0      25.0       4.0
2020-05-20 12:00:00  13.0     5.0  28.0      22.0       4.0
2020-05-18 12:00:00  18.0    26.0  13.0      23.0       5.0
2020-05-19 12:00:00  13.0    27.0  15.0      16.0       5.0
2020-05-20 12:00:00  25.0    11.0   6.0      21.0       5.0
2020-05-18 12:00:00  23.0    21.0   3.0      22.0       6.0
2020-05-19 12:00:00   6.0    12.0  10.0       2.0       6.0
2020-05-20 12:00:00   2.0    12.0  12.0      14.0       6.0
Related