根据时间合并数据帧

时间:2016-02-04 21:15:31

标签: python pandas merge

我从两个不同的气象站获取某个位置的数据。 80年代安装了一个站,90年代中期安装了另一个站。由于仪器错误,旧站的读数变得不可靠。新站也有几个缺失记录的实例。

我计划在安装新电台之前使用旧电台的数据创建完整的天气配置文件,并附加新电台的数据。当新站(NaN)出现仪器故障时,我也希望使用旧站的数据。

 df_new =pd.DataFrame(
{'Date': {0: '01/01/1994', 1: '01/02/1994', 2: '01/03/1994', 3: '01/04/1994'},
 'Rain': {0: 0, 1: 0, 2: 0, 3: 0},
 'TMAX': {0: -5.5, 1: np.nan, 2: -1.5, 3: np.nan},
 'TMIN': {0: -11.64, 1: -10.55, 2: np.nan, 3: -11.41},
 'WIND': {0: 4.1,  1: 6.8,  2: 5.4,  3: 9.6}})

df_old = pd.DataFrame(    
     {'Date': {0: '01/01/1980', 1: '01/02/1980', 2: '01/03/1980', 3: '01/04/1980'},
     'Rain': {0: 0, 1: 0, 2: 0, 3: 0},
     'TMAX': {0: -5.5, 1: -3.5, 2: -1.5, 3: -2.8},
     'TMIN': {0: -11.64,  1: -10.55,  2: -14.33, 3: -11.41}, 
      'WIND': {0: 4.1,  1: 6.8,  2: 5.4, 3: 9.6}})

如何组合两个df并创建一个新的df(df_complete)?

df_complete
Date       Rain TMAX  TMIN  WIND
01/01/1980  0   -5.5 -11.64 4.1
01/02/1980  0   -3.5 -10.55 6.8
01/03/1980  0   -1.5 -14.33 5.4
.
.
01/01/1994  0   -5.5 -11.64 4.1
01/02/1994  0    5.7 -10.55 6.8
01/03/1994  0   -1.5 -10.58 5.4
.
.
12/31/2014  0   -4.9 -10.21 3.5

为了让自己更清楚,使用 df_old

中的值替换了df_new中的NaN值

3 个答案:

答案 0 :(得分:2)

尝试使用combine_first()。

import numpy as np
import pandas as pd
from pandas.tseries.offsets import DateOffset

df_new =pd.DataFrame(
{'Date': {0: '01/01/1994', 1: '01/02/1994', 2: '01/03/1994', 3: '01/04/1994'},
 'Rain': {0: 0, 1: 0, 2: 0, 3: 0},
 'TMAX': {0: -5.5, 1: np.nan, 2: -1.5, 3: np.nan},
 'TMIN': {0: -11.64, 1: -10.55, 2: np.nan, 3: -11.41},
 'WIND': {0: 4.1,  1: 6.8,  2: 5.4,  3: 9.6}})

df_old = pd.DataFrame(    
     {'Date': {0: '01/01/1980', 1: '01/02/1980', 2: '01/03/1980', 3: '01/04/1980'},
     'Rain': {0: 0, 1: 0, 2: 0, 3: 0},
     'TMAX': {0: -5.5, 1: -3.5, 2: -1.5, 3: -2.8},
     'TMIN': {0: -11.64,  1: -10.55,  2: -14.33, 3: -11.41}, 
      'WIND': {0: 4.1,  1: 6.8,  2: 5.4, 3: 9.6}})

# Date Type Cast 
df_old['Date'] = pd.to_datetime(df_old['Date'])
df_new['Date'] = pd.to_datetime(df_new['Date'])
# I'm assuming a 14 year roll forward.
df_old['DateForward'] = df_old['Date'] + pd.DateOffset(years=14)
df_old.set_index('DateForward',inplace=True)
df_new.set_index('Date',inplace=True)
df_new.combine_first(df_old).reset_index(drop=True)

        Date  Rain  TMAX   TMIN  WIND
0 1980-01-01     0  -5.5 -11.64   4.1
1 1980-01-02     0  -3.5 -10.55   6.8
2 1980-01-03     0  -1.5 -14.33   5.4
3 1980-01-04     0  -2.8 -11.41   9.6

答案 1 :(得分:1)

首先,标记您的数据,以便在合并后知道来源:

df_old['source'] = 'old' 
df_new['source'] = 'new'

使用辅助函数只需两个语句即可实现结果:

df_combined = combine(df_new, df_old, 
                      cols=['TMAX', 'TMIN', 'WIND'], 
                      on='Date')
pd.concat([df_old, df_combined])
=>
   Date        Rain  TMAX  TMIN  WIND source updated
0  2015-01-02     0     0     6     0    old     NaN
1  2015-01-03     1     8    -4     9    old     NaN
2  2015-01-04     1    -3     9    12    old     NaN
3  2015-01-05     0    -4     5    16    old     NaN
4  2015-01-06     0    -2     9     5    old     NaN
5  2015-01-07     1     3     8    12    old     NaN
6  2015-01-08     0     9    -2     6    old     NaN
7  2015-01-09     1     7    -3    11    old     NaN
...
19 2015-01-21     0    -5    -1     8    new        
20 2015-01-22     0     2    -5     1    new        
21 2015-01-23     1     7     8    17    new        
22 2015-01-24     0     6     5     8    new    TMAX
23 2015-01-25     1    -3     0    13    new    TMAX
24 2015-01-26     1     4    -3     8    new        
25 2015-01-27     0     1    -2     7    new    TMIN
26 2015-01-28     0    -4     5     0    new        
27 2015-01-29     1     9    -3     3    new    TMIN

请注意,combine还会告诉我们哪些值已更新。

combine功能如下。它将我原来的答案概括为pandas.combine_first功能的选择性版本。选择性意义,您可以指定合并键和列,而无需摆弄索引:

def combine(df_left, df_right, cols=None, on=None):
    def check(r):
        updated = []
        for c in cols:
            xc = '%s_x' % c
            yc = '%s_y' % c
            if math.isnan(r[xc]):
                r[xc] = r[yc]
                updated.append(c)
        r['updated'] = ','.join(updated)
        return r
    left_expanded = df_left.merge(df_right, on=on, how='left')
    left_expanded = left_expanded.apply(check, axis=1)
    columns = [('%s' % c, c.replace('_x', '')) 
                for c in left_expanded.columns] 
    left_expanded.rename(columns=dict(columns), inplace=True)
    return left_expanded[list(df_left.columns) + ['updated']]

我的初步答案仍可在历史记录中使用,或使用full solution。感谢Dickster bringing up combine_first,这激发了我对原始方法的概括。

答案 2 :(得分:0)

尝试pandas concatentate:

ne = @newevent.Master

我真的不确定你想要用NaN做些什么。您是否尝试使用来自每个数据帧的匹配日期填充空观察值?

如果它们具有相同的观察数量/顺序,您可以执行以下操作:

ne = @newevent.master