2017-07-26 13 views
1

私はDataFrameの列を持ち、そのデータは別の列の値に依存しています。残念ながら、データを収集しているソースは、最初のカラム('host_id')の値が最初に与えられたときに、2番目のカラム('job_id')の値のみを提供します。その結果、'job_id'にはNaNの値が多く含まれています。別の行の別の列の値に基づいて列の値を行単位でコピーする単純なDataFrameメソッドはありますか?

In [1]: import pandas as pd, numpy as np 

In [2]: df = pd.DataFrame({'run_id' : range(10), 
    ...:     'host_id': ['a', 'b', 'c', 'd', 'e', 'a', 'd', 'c', 'a', 'e'], 
    ...:     'job_id': [100253, 100254, 100255, 100256, 100257, np.nan, np.nan, np.nan, np.nan, np.nan]}) 

In [3]: df 
Out[3]: 
    host_id job_id run_id 
0  a 100253.0  0 
1  b 100254.0  1 
2  c 100255.0  2 
3  d 100256.0  3 
4  e 100257.0  4 
5  a  NaN  5 
6  d  NaN  6 
7  c  NaN  7 
8  a  NaN  8 
9  e  NaN  9 

所望の出力が'host_id'と同じように'job_id'繰り返しを持っているだろう:

host_id job_id run_id 
0  a 100253.0  0 
1  b 100254.0  1 
2  c 100255.0  2 
3  d 100256.0  3 
4  e 100257.0  4 
5  a 100253.0  5 
6  d 100256.0  6 
7  c 100255.0  7 
8  a 100253.0  8 
9  e 100257.0  9 

私が思いついた解決策はただ'host_id''job_id'列を抽出することで、行を削除NaNで、元のDataFrameで左マージを使用し、結果の列の名前を変更/並べ替えます。

In [3]: host_job_mapping = df[['host_id', 'job_id']].dropna(subset=['job_id']) 

In [4]: host_job_mapping 
Out[4]: 
    host_id job_id 
0  a 100253.0 
1  b 100254.0 
2  c 100255.0 
3  d 100256.0 
4  e 100257.0 

In [5]: df = pd.merge(df, host_job_mapping, how='left', on='host_id') 

In [6]: df 
Out[6]: 
    host_id job_id_x run_id job_id_y 
0  a 100253.0  0 100253.0 
1  b 100254.0  1 100254.0 
2  c 100255.0  2 100255.0 
3  d 100256.0  3 100256.0 
4  e 100257.0  4 100257.0 
5  a  NaN  5 100253.0 
6  d  NaN  6 100256.0 
7  c  NaN  7 100255.0 
8  a  NaN  8 100253.0 
9  e  NaN  9 100257.0 

In [7]: df = df.rename(columns={'job_id_y': 'job_id'})[['host_id', 'job_id', 'run_id']] 

In [8]: df 
Out[8]: 
    host_id job_id run_id 
0  a 100253.0  0 
1  b 100254.0  1 
2  c 100255.0  2 
3  d 100256.0  3 
4  e 100257.0  4 
5  a 100253.0  5 
6  d 100256.0  6 
7  c 100255.0  7 
8  a 100253.0  8 
9  e 100257.0  9 

これは動作しますが、それは特にエレガントないないようです。これを達成するためのより簡単で簡単な方法がありますか(applyに頼らないで)?

あなたが、その後 host_idとでグループが forward fillを行うことができます

答えて

1

:取得まず、

df['job_id'] = df.job_id.groupby(df.host_id).ffill() 

またはあなたの独創的なアプローチ以下:

df.groupby('host_id', as_index=False).ffill() 

# host_id job_id run_id 
#0  a 100253.0 0 
#1  b 100254.0 1 
#2  c 100255.0 2 
#3  d 100256.0 3 
#4  e 100257.0 4 
#5  a 100253.0 5 
#6  d 100256.0 6 
#7  c 100255.0 7 
#8  a 100253.0 8 
#9  e 100257.0 9 

他の列の値が欠落している可能性がある場合host_idjob_idとの関係その後、host_idからjob_idを取得するためにmapを使用します。

df.job_id = df.host_id.map(df.set_index('host_id').job_id.dropna()) 
+1

まあ、これは間違いなく* *よりエレガントな私の解決策よりもです!私は 'ffill()'の解決策が好きです。私は、このアルゴリズムが "フォワードフィル"と呼ばれていたので、私は何を検索するのか分からなかったと思います。 – SethMMorton

+0

いくつかのテストをした後、私は同じ非常に大きなデータセットに対して 'ffill'メソッドが約1.9秒かかったが、' set_index'/'map'メソッドは約0.23秒かかったことを発見しました。私は代わりに2番目のバージョンを使用するように見えます。複数のオプションをくれてありがとう! – SethMMorton

+0

問題ありません。喜んでそれが役立ちます。 – Psidom

関連する問題