2017-08-07 90 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]