2016-02-04 71 views
0

我有來自兩個不同氣象站的位置數據。一個電臺在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_new的NaN值使用值代替從df_old

+0

你沒有真正表達過一個問題。你想要解決什麼問題? – Brian

+0

請讓我知道它是否更容易理解。 –

+0

是的 - 這是很好的添加一個簡單的方法來啓動示例數據遊戲。這增加了您及時回答的可能性。在我的例子中,我用to_dict()將其渲染出來。 – Dickster

回答

1

首先,標記您的資料,讓您知道源一次合併:

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

使用幫助函數可以實現結果機智^ h只需兩個語句:

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,這激勵我推廣我的原始方法。

0

嘗試大熊貓concatentate:

together = pd.concat([df_new, df_old]) 

我真的不知道你正在尋找與NaN的做什麼。你是否試圖用每個數據框的匹配日期填充空觀察值?

,如果他們有意見相同數量/爲了你也許可以這樣做:

df_new['TMAX'].fillna(df_old['TMAX']) 
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 
+0

好的方法。不知道有關'combine_first'。謝謝。 – miraculixx