2017-08-07 87 views
1

我有兩列「的ID」和「名稱」的數據幀DF1提取特定行 -從數據幀

ids  names 
fhj56 abc 
ty67s pqr 
yu34o xyz 

我有具有某些列是另一個數據幀DF2 -

user  values      
1  ['fhj56','fg7uy8'] 
2  ['glao0','rt56yu','re23u'] 
3  ['fhj56','ty67s','hgjl09'] 

我的結果應該給我那些來自df2的用戶,他們的值至少包含df1中的一個id,並且告訴哪些id負責將它們放入結果表中。結果應該看起來像 -

user  values_responsible  names 
    1  ['fhj56']    ['abc'] 
    3  ['fhj56','ty67s']  ['abc','pqr'] 

用戶2不產生表來,因爲沒有它的價值在DF1存在。

我試圖如下做到這一點 -

df2.query('values in @df1.ids') 

但是,這似乎並沒有很好地工作。

+0

您需要UNNEST你列'values' – Wen

回答

2

你可以通過行迭代,然後使用.loc在一起與isin找到df2的匹配行。我轉換這個過濾數據幀轉換成字典

ids = [] 
names = [] 
users = [] 
for _, row in df2.iterrows(): 
    result = df1.loc[df1['ids'].isin(row['values'])] 
    if not result.empty: 
     ids.append(result['ids'].tolist()) 
     names.append(result['names'].tolist()) 
     users.append(row['user']) 

>>> pd.DataFrame({'user': users, 'values_responsible': ids, 'names': names})[['user', 'values_responsible', 'names']] 
    user values_responsible  names 
0  1   [fhj56]  [abc] 
1  3  [fhj56, ty67s] [abc, pqr] 

或者,整潔數據:

ids = [] 
names = [] 
users = [] 
for _, row in df2.iterrows(): 
    result = df1.loc[df1['ids'].isin(row['values'])] 
    if not result.empty: 
     ids.extend(result['ids'].tolist()) 
     names.extend(result['names'].tolist()) 
     users.extend([row['user']] * len(result['ids'])) 

>>> pd.DataFrame({'user': users, 'values_responsible': ids, 'names': names})[['user', 'values_responsible', 'names']]) 
    user values_responsible names 
0  1    fhj56 abc 
1  3    fhj56 abc 
2  3    ty67s pqr 
+0

在大熊貓行到行操作是一個比較骯髒的方式去了解這個問題。 [這裏是](https://stackoverflow.com/a/7837947/4365003)一個很好的解釋。在許多情況下,可以通過逐行迭代直觀地解決的數據幀問題也可以通過切割器過濾或「應用」或「映射」功能的應用來解決。 – RagingRoosevelt

+1

是的,逐行並不是最有效的,但這是因爲數據開始時並不整齊。 – Alexander

1

我會重構你的第二個數據框(基本上,規範化你的數據庫)。類似於

user  gid  id      
1  1  'fhj56' 
1  1  'fg7uy8' 
2  1  'glao0' 
2  1  'rt56yu' 
2  1  're23u' 
3  1  'fhj56' 
3  1  'ty67s' 
3  1  'hgjl09' 

然後,您所要做的就是合併id列上的第一個和第二個數據幀。

r = df2.merge(df1, left_on='id', right_on='ids', how='left') 

您可以排除其中某些id沒有匹配名稱的任何gid。

r[~r[gid].isin( r[r['names'] == None][gid].unique() )] 

其中r[r['names'] == None][gid].unique()查找所有沒有名稱,然後r[~r[gid].isin(...)]爭奪僅限未在isin列表參數項導報。


如果您有更多的ID組,第二個表可能看起來像

user  gid  id      
1  1  'fhj56' 
1  1  'fg7uy8' 
1  2  '1asdf3' 
1  2  '7ada2a' 
1  2  'asd341' 
2  1  'glao0' 
2  1  'rt56yu' 
2  1  're23u' 
3  1  'fhj56' 
3  1  'ty67s' 
3  1  'hgjl09' 

這將等同於

user  values      
1  ['fhj56','fg7uy8'] 
1  ['1asdf3', '7ada2a', 'asd341'] 
2  ['glao0','rt56yu','re23u'] 
3  ['fhj56','ty67s','hgjl09'] 
2

試試這個,使用UNNEST列表細胞的想法。

Temp_unnest = pd.DataFrame([[i, x] 
       for i, y in df['values'].apply(list).iteritems() 
        for x in y], columns=list('IV')) 

Temp_unnest['user']=Temp_unnest.I.map(df.user) 
df1.index=df1.ids 
Temp_unnest.assign(names=Temp_unnest.V.map(df1.names)).dropna().groupby('user')['V','names'].agg({(lambda x: list(x))}) 


Out[942]: 
        V  names 
      <lambda> <lambda> 
user        
1   [fhj56]  [abc] 
3  [fhj56, ty67s] [abc, pqr]