2017-12-20 16 views
2

2番目のデータフレームの属性に基づいて既存のpandasデータフレームに列を追加する必要があります。私は私の正確な要件を示すために最小限の例を作りました。別のデータフレームに基づいてPandasで新しい列を作成

私は2つのデータフレームを持っている

、名前のペアを表す1つ、そして二人の個人間の相互作用を表す他は:

>>> names 
    id_a id_b 
0 ben jack 
1 jack ben 
2 jill amir 
3 wilma jill 
4 amir wilma 

>>> interactions 
    individual1 individual2 
0  jill  jack 
1  jack  jill 
2  wilma  jill 
3  amir  jill 
4  amir  jack 
5  jack  amir 
6  jill  amir 

何が必要なのは、基本的にこれです:namesの名前の各ペアについて、Iこれらの2つの名前の間の対話数をカウントする必要があるので、names['id_a']の中の行数はまたはinteractions['individual2']names['id_b']のいずれかで、行数はinteractions['individual1']またはinteractions['individual2']のいずれかです。名前が重複していても(ID_aがbenであり、id_bがジャックである行と、その名前が逆になっている行(id_aは次のようになります)場合でも、このカウントは名前のすべての行について列num_interactionsに含める必要があります。ジャックとID_Bベンである)、num_interactionsは、それらの行の両方のために含まれなければならない)

は、得られたデータフレームは、次のようになります。

私は

これはうまく動作しますが何をやったか

>>> names 
    id_a id_b num_interactions 
0 ben jack    0.0 
1 jack ben    0.0 
2 jill amir    2.0 
3 wilma jill    1.0 
4 amir wilma    0.0 
    enter code here 

をしかし、それは醜い、読みにくい、非効率的で、私は良い方法が必要であることを知っている!たぶん、いくつかのマージの並べ替えが、私は本当にそれは複雑な基準をどのように動作するか分からない...

for i in range(len(names)): 
    names.loc[i, 'num_interactions'] = len(
     interactions[((interactions['individual1'] == names.loc[i, 'id_a']) & 
         (interactions['individual2'] == names.loc[i, 'id_b'])) | 
        ((interactions['individual2'] == names.loc[i, 'id_a']) & 
         (interactions['individual1'] == names.loc[i, 'id_b'])) 
        ]) 

と私の例を再現するために、あなたは、あなたがこれで遊ぶしたい場合

をデータフレーム上記のダミーのデータフレームを再現するためにこれを使用することができます。

import pandas as pd 
names = pd.DataFrame(data={'id_a': ['ben', 'jack', 'jill', 'wilma', 'amir'], 
          'id_b': ['jack', 'ben', 'amir', 'jill', 'wilma']}) 

interactions = pd.DataFrame(data={'individual1': ['jill', 'jack', 
                'wilma', 'amir', 
                'amir', 'jack', 'jill'], 
            'individual2': ['jack', 'jill', 'jill', 
                'jill', 'jack', 'amir', 
                'amir']}) 

ありがとうございます!

+0

'名前['num_interactions'] = interactions.groupby(['individual1'、 'individual2'])。transform( 'count')'? –

+0

@LucasDreslそれは、残念ながら、ペアの間で変化する順序を処理しません。 –

答えて

1

順序は関係ありません。各データフレームを列で並べ替えることができます。 2番目のデータフレームの場合は、各グループの相互作用をgroupby + countとカウントし、結果と最初のデータフレームで左外部mergeを実行します。

i = pd.DataFrame(np.sort(names, axis=1)) 
j = pd.DataFrame(np.sort(interactions, axis=1)) 

k = j.groupby(j.columns.tolist())[0].count().reset_index(name='count') 
df = i.merge(k, on=[0, 1], how='left')\ 
     .fillna(0)\ 
     .rename(columns={0 : 'id_a', 1 : 'id_b'}) 
df.iloc[:, :2] = names.values 

df 

    id_a id_b count 
0 ben jack 0.0 
1 ben jack 0.0 
2 amir jill 2.0 
3 jill wilma 1.0 
4 amir wilma 0.0 
+0

ありがとう!これは終わりですが、私はもっと明確にすべきでした。名前、データフレームに「ジャッキー・ベン」と「ベン・ジャック」の行がある場合は、そのそれぞれを組み込む必要があるため、ドロップできません重複と並べ替え。私は私の元のポストで明らかにする。 – sacul

+0

@sacul私の編集を見ますか?私は問題を修正しました...実際にはとても簡単でした。 –

+0

うん、それは動作します!あなたの戦略をベースにして混乱させようとするので、id_aとid_bが変更されていないデータフレームで終わることができます。 – sacul

0

申し訳ありませんが、それは私がなどの新しい列を追加しますが、あなたのアイデアを取得し、それをどのように改善できるか少し醜いです... まず私は名前のすべてのペアが一意であることを前提としています。だから私は、私は再びだから、最後に、私はちょうど相互作用に各IDを数える相互作用

interactions_new = pd.DataFrame(pd.concat([interactions.iloc[:, 0] + '-' + interactions.iloc[:, 1], 
           interactions.iloc[:, 1] + '-' + interactions.iloc[:, 0]], 
              axis=0), 
           columns=['pair']) 
interactions_new['count'] = np.ones(len(interactions_new)) 

count_id = interactions_new.join(names_ids['id'], on='pair', how='left').groupby('id').count().loc[:, ['count']] 
count_id['id'] = count_id.index 

の各ペアを反転相互作用して、これらのIDを参加次に、各ペアにID

names_ids = pd.DataFrame(pd.concat([names.iloc[:, 0] + '-' + names.iloc[:, 1], 
         names.iloc[:, 1] + '-' + names.iloc[:, 0]], 
            axis=0), 
         columns=['pair']) 
names_ids['id'] = names_ids.index 
names_ids.index = names_ids.pair 

を与える:

names_ids.index = names_ids.id 
result = count_id.join(names_ids.pair.iloc[:len(names_ids)/2], on='id', how='left') 
result['count'] /= 2 
print result 
ループの醜いしかし、誰

と私が取得:

 count id  pair 
id       
2.0  2 2.0 jill-amir 
3.0  1 3.0 wilma-jill 
+0

クール、これは私が思っていたものとは違うアプローチですが、効果的です。あなたがペアを反転すると、カウントが2倍になります(私の元の例では、jill-amirのカウントは2でなければならず、wilma-jillのカウントは1に終わったはずです。値はdoubleです) – sacul

+0

@sacul fixed :) – mm441

関連する問題