2017-04-22 22 views
1

次のような問題がある:Pythonのパンダ条件付き更新

  • 列は次のとおりです:姓、名、部署(コンサルティングやセールス、それぞれCとSに略す)、従業員ID、および給与。この例では、salaryカラムには何も機能はありません。実際には他の列がたくさんあることを強調するだけです。
  • 特定の名前はの間に重複しています。
  • これが役立つかどうかはわかりませんが、first_name + last_name + idは各行に固有の識別子を形成します。これは、以前の重複除去シナリオで最も重複しているものを識別する最短の一意の識別子であるため、これを使用する必要があります(1行目と2行目を参照)。一歩進んでこの識別子をさらに列に結びつけることもできますが、これは非常に洗練されたソリューションではありません。

次のように最初のデータフレームは、次のとおり

first_name | last_name | id | dept | salary 
------------------------------------------- 
sarah  | jones  | C1 | C | 60000 
sarah  | jones  | C2 | C | 55000 
robert  | jones  | C3 | C | 50000 
alice  | clarke | C4 | C | 40000 
alice  | clarke | S1 | S | 40000 
thomas  | roberts | S2 | S | 45000 

I行4(コンサルティング DEPTに関連付けられているalice clarke行)を削除し、行5を維持したいが、コンサルティングを保持するだろう部門ID。それは私が持っているべきである:

first_name | last_name | id | dept | salary 
------------------------------------------- 
sarah  | jones  | C1 | C | 60000 
sarah  | jones  | C2 | C | 55000 
robert  | jones  | C3 | C | 50000 
alice  | clarke | C4 | S | 40000 
thomas  | roberts | S2 | S | 45000 

(IRL:私は2つのデータソースを有し、D1及びD2 D2のデータは、ISO規格のような、より高品質であるが、D1によって使用されるIDがより広く認識されていますD1とD2が同じ行を与えるたびに、D1 IDとD2の実際のデータを使用したいと思います。

実際の問題はこのMVWEよりも少し複雑です重複除去シナリオ)。私は、重複削除や条件付きで値を上書きするという私の以前の質問のいくつかを使って問題を切り詰めようとしましたが、問題を適切にモジュール化できなかったために全体的な問題にうまく対処できませんでした。条件付きで行を更新する場合のThis質問が役に立ちます。

+1

明確にするために:あなたは常にSの複製を保持したいが、CのIDを保持したいのですか? – DyZ

+1

もう1つ混乱している点:alice clarke C5もあるとします。さて、Alice clarke S1はC4かC5の複製ですか? – DyZ

+1

例は非常に有用ですが、基本的には必要ですが、実際にどの基準を適用したいかを言い換えることに代わるものではありません。 – DSM

答えて

1

いくつかのコメント投稿者の例では少し詳しく説明していますが、正しく理解すれば、基本的に2つのデータフレームがあり、ある情報と別の情報を別のものから保持したい。 combine_first()はトリックを行う必要があり、あなたは、実際には2つのデータフレームから始まり、それらをマージする制御であるしていると仮定すると:

csv = io.StringIO(u''' 
first last  id dept salary 
sarah jones C1 C  60 
sarah jones C2 C  55 
robert jones C3 C  50 
alice clarke C4 C  40 
thomas roberts S2 S  45 
''') 

df = pd.read_csv(csv, delim_whitespace = True) 

csv2 = io.StringIO(u''' 
first last  id dept salary 
alice clarke S1 S  43 
''') 

df2 = pd.read_csv(csv2, delim_whitespace = True) 
df2.drop('id', axis = 1) 

print df2.set_index(['first','last']).combine_first(df.set_index(['first','last'])).reset_index() 

出力:

first last dept id salary 
0 alice clarke S  C4 43.0 
1 robert jones C  C3 50.0 
2 sarah jones C  C1 60.0 
3 sarah jones C  C2 55.0 
4 thomas roberts S  S2 45.0 

そして、あなたがに合うように、もちろん、あなたが並べ替えることができますその点。

0

出発点は、あなたが提供する最初のデータフレームであり、2つのだけdept種類があることを考えるならば、することができますgroupby名、その後apply選択/スワップ機能:

# using initial data frame provided, copied to clipboard 
df = pd.read_clipboard().drop(0, 0).drop(['|','|.1','|.2','|.3'], 1) 

def choose_data(data, chosen_field, chosen_value, swap_field): 
    if len(data[chosen_field].unique()) > 1: 
     chosen = data[data[chosen_field]==chosen_value] 
     chosen[swap_field] = data.ix[data[chosen_field]!=chosen_value, swap_field].values 
     return chosen 
    return data 

(df.groupby(['first_name','last_name'], as_index=False) 
    .apply(choose_data, 
      chosen_field='dept', 
      chosen_value='S', 
      swap_field='id') 
    .reset_index(drop=True) 
    .sort_values('id') 
) 

収量:

reset_index()sort_values()は基本的に化粧品のある
first_name last_name id dept salary 
0  sarah  jones C1 C 60000.0 
1  sarah  jones C2 C 55000.0 
2  robert  jones C3 C 50000.0 
3  alice clarke C4 S 40000.0 
4  thomas roberts S2 S 45000.0 

注意が、すべてのことが本当に必要だgroupby()apply()です。