2016-05-31 5 views
2

私は2つのパンダデータフレームを持っています1つの(日付)列に複数の列(例えば3)とおおよそ、 。私はまた、それらの間の違い(日)を返すしたい。各データセットは約50,000行です。私は内部結合に最も関心がありますが、 "残余物"も興味深いものです。 "完全一致"観測の大部分は、各データフレームに複数回存在します。パンダ:1つの列の近似結合、他の列の完全一致

私は(!私が知っている、愚かである)、文字列としてそれらの全ての連結にdifflib.get_close_matchesを使用しようとしてきたが、され、常に正確な一致を与えるものではありません。

df1 = pd.DataFrame({'index': ['a1','a2','a3','a4'], 'col1': ['1232','432','432','123'], 'col2': ['asd','dsa12','dsa12','asd2'], 'col3': ['1','2','2','3'], 'date': ['2010-01-23','2016-05-20','2010-06-20','2008-10-21'],}).set_index('index') 

df1 
Out[430]: 
     col1 col2 col3  date 
index        
a1  1232 asd 1 2010-01-23 
a2  432 dsa12 2 2016-05-20 
a3  432 dsa12 2 2010-06-20 
a4  123 asd2 3 2008-10-21 

df2 = pd.DataFrame({'index': ['b1','b2','b3','b4'], 'col1': ['132','432','432','123'], 'col2': ['asd','dsa12','dsa12','sd2'], 'col3': ['1','2','2','3'], 'date': ['2010-01-23','2016-05-23','2010-06-10','2008-10-21'],}).set_index('index') 

df2 
Out[434]: 
     col1 col2 col3  date 
index        
b1  132 asd 1 2010-01-23 
b2  432 dsa12 2 2016-05-23 
b3  432 dsa12 2 2010-06-10 
b4  123 sd2 3 2008-10-21 
:私は最初の完全一致をループする必要があるとし、このグループ内で最も近いマッチを見つけるが、私はちょうどそれを得るように見えることはできません...

データフレームは次のようになり最後に

私が何かのようにしたい:

 col1 col2 col3  date diff match_index 
index        
a1  1232 asd 1 2010-01-23 nan   nan 
a2  432 dsa12 2 2016-05-20 -3   b2 
a3  432 dsa12 2 2010-06-20 10   b3 
a4  123 asd2 3 2008-10-21 nan   nan 
a5  123 sd2 3 2008-10-21 nan   b4 

かどうかは、私が好きなジョインだけのインナーとの双方向簡単です:

 col1 col2 col3  date diff match_index 
index              
a2  432 dsa12 2 2016-05-20 -3   b2 
a3  432 dsa12 2 2010-06-20 10   b3 
+0

あなたが探しているもののそれぞれに別々の質問をしても意味があります。 – fmarc

答えて

2

Hej mate、

これが合うかどうかわかりません。それはあなたが望むものを多かれ少なかれ達成しますが、実際にはマージを実行しません。 1つの列のみに基づいてdf1をサブセット化するのではなく、groupbyを使用して複数の列を一致させ、両方のデータフレームで行うことを除いて、このquestionと同じ考え方に従います。 mergeコマンドを明示的に含める場合は、内部結合がうまくいれば答えの一番下を確認してください。そのためのスニペットが含まれています。 mergeコマンドで

In [349]: df_final 
Out[349]: 
    col1 col2 col3  date diff match_index 
0 1232 asd 1 2010-01-23  NaT   NaN 
1 432 dsa12 2 2016-05-20 -3 days   b2 
2 432 dsa12 2 2010-06-20 10 days   b3 
3 123 asd2 3 2008-10-21  NaT   NaN 
4 132 asd 1 2010-01-23  NaT   NaN 
5 123 sd2 3 2008-10-21  NaT   NaN 

In [208]: pd.merge(df1_mod, df2.drop('date', axis=1), on=['col1', 'col2', 'col3']).drop_duplicates() 
Out[208]: 
    col1 col2 col3  date diff match_index 
0 432 dsa12 2 2016-05-20 -3 days   b2 
2 432 dsa12 2 2010-06-20 10 days   b3 

みなさ場合sklearn.neighborsからPD として

輸入パンダはNearestNeighbors

def find_nearest(group, df2, groupname): 
    try: 
     match = df2.groupby(groupname).get_group(group.name) 
     match['date'] = pd.to_datetime(match.date, unit = 'D') 
     nbrs = NearestNeighbors(1).fit(match['date'].values[:, None]) 
     dist, ind = nbrs.kneighbors(group['date'].values[:, None]) 

     group['date1'] = group['date'] 
     group['date'] = match['date'].values[ind.ravel()] 
     group['diff'] = (group['date1']-group['date']) 
     group['match_index'] = match.index[ind.ravel()] 
     return group 
    except KeyError: 
     return group 

#change dates from string to datetime 
df1['date'] = pd.to_datetime(df1.date, unit = 'D') 
df2['date'] = pd.to_datetime(df2.date, unit = 'D') 

#find closest dates and differences 
keys = ['col1', 'col2', 'col3'] 
df1_mod = df1.groupby(keys).apply(find_nearest, df2, keys) 

#fill unmatched dates 
df1_mod.date1.fillna(df1_mod.date, inplace=True) 

df2_mod = df2.groupby(keys).apply(find_nearest, df1, keys) 
df2_mod.date1.fillna(df2_mod.date, inplace=True) 

#drop original column 
df1_mod.drop('date', inplace=True, axis=1) 
df1_mod.rename(columns = {'date1':'date'}, inplace=True) 

df2_mod.drop('date', inplace=True, axis=1) 
df2_mod.rename(columns = {'date1':'date'}, inplace=True) 
df2_mod['diff'] = -df2_mod['diff'] 

#drop redundant values 
df2_mod.drop(df2_mod[df2_mod.match_index.str.len()>0].index, inplace=True) 

#merge the two 
df_final = pd.merge(df1_mod, df2_mod, how='outer') 

をインポートこれは、次の結果が得られますコメント:

df1 = pd.DataFrame({'index': ['a1','a2','a3','a4'], 'col1': ['1232','1432','432','123'], 'col2': ['asd','dsa12','dsa12','asd2'], 'col3': ['1','2','2','3'], 'date': ['2010-01-23','2016-05-20','2010-06-20','2008-10-21'],}).set_index('index') 

次が得られます。

In [351]: df_final 
Out[351]: 
    col1 col2 col3  date diff match_index 
0 1232 asd 1 2010-01-23  NaT   NaN 
1 1432 dsa12 2 2016-05-20  NaT   NaN 
2 432 dsa12 2 2010-06-20 10 days   b3 
3 123 asd2 3 2008-10-21  NaT   NaN 
4 132 asd 1 2010-01-23  NaT   NaN 
5 123 sd2 3 2008-10-21  NaT   NaN 
+0

ありがとうございました!これはほとんどですが、 'col1'、' col2'、 'col3'のすべてをマッチさせたいのですが、' col3'という1つのカラムでのみマッチします。 astype(str)+ df1 ['col2'] astype(str)+ df1 ['col3'] astype(str)+ df1 ['col1']を使用して、 'しかし、それはそれを持っていないだろう...正確な一致が文字列ではなく数値である場合にのみ動作するように思われる? –

+0

残念ながら数値と文字列は関係ありませんが、なぜ動作しないのかまだ分かりませんが、ValueError:Foundサンプルは0個のサンプル(shape =(0、1))while最低1は必要です。」 –

+0

CAR ERL、私はまったくフォローしません。可能であれば、実行中のコードを提供して前述のエラーメッセージを表示できますか? –

関連する問題