python数据帧中行和列之间的公共元素

python数据帧中行和列之间的公共元素,python,dataframe,Python,Dataframe,我有两个数据帧。第一个,如下所示,有三列 Col_1 Col_2 Col_3 aaa dfd ccc sdf jjj sge rty fgh rtg hji dfg hyt lkj bgh dcf 在每一行中,有一个元素与下面显示的第二个数据框中的一个元素相同(当然,第二个数据框中的元素不必具有任何特定顺序) 我的目标是遍历第一个数据帧中的每一行,并找到第二个数据帧中的公共元素。然后将该元素带到行的开头。预

我有两个数据帧。第一个,如下所示,有三列

Col_1   Col_2   Col_3
aaa     dfd     ccc
sdf     jjj     sge
rty     fgh     rtg
hji     dfg     hyt
lkj     bgh     dcf
在每一行中,有一个元素与下面显示的第二个数据框中的一个元素相同(当然,第二个数据框中的元素不必具有任何特定顺序)

我的目标是遍历第一个数据帧中的每一行,并找到第二个数据帧中的公共元素。然后将该元素带到行的开头。预期结果如下:

预期结果

Col_1   Col_2   Col_3
ccc     aaa     dfd
sge     sdf     jjj
fgh     rty     rtg
dfg     hji     hyt
dcf     lkj     bgh

任何帮助都将不胜感激

这里有一个可能的解决方案,使用列表理解(
df1
df2
是两个数据帧):

# turn 2nd dataframe into lookup list
lookup = df2['list'].tolist()

for index, row in df1.iterrows():
    # if column 1 matches do nothing
    # if column 2 matches list, reorder column 1 and 2, ignore 3
    if row['Col_2'] in lookup:
        col1 = row['Col_1']
        col2 = row['Col_2']
        df1.loc[index, 'Col_1'] = col2
        df1.loc[index, 'Col_2'] = col1
    # if column 3 matches, reorder values
    if row['Col_3'] in lookup:
        col1 = row['Col_1']
        col2 = row['Col_2']
        col3 = row['Col_3']
        df1.loc[index, 'Col_1'] = col3
        df1.loc[index, 'Col_2'] = col1
        df1.loc[index, 'Col_3'] = col2
使用pandas DataFrame的方法,您可以在一行中完成。这将比手动迭代行更快

它只使用pandas并在行级别工作,首先检查行元素是否在
ls
中,对返回的二进制指示符进行排序(对行的前面为True),然后按此顺序重新索引要排序的行。然后,它将结果广播回原始行

import pandas as pd

df = pd.DataFrame({'col1':['aaa','sdf','rty','hji','lkj'],
                   'col2':['dfd','jjj','fgh','dfg','bgh'],
                   'col3':['ccc','sge','rtg','hyt','dcf']})     

ls = pd.Series(['ccc','sge','fgh','dfg','dcf'])

df = df.apply(lambda x: x[(~x.isin(ls)).argsort()], 
              axis=1, 
              result_type='broadcast')
返回:

    col1  col2   col3
0   ccc    aaa   dfd
1   sge    sdf   jjj
2   fgh    rty   rtg
3   dfg    hji   hyt
4   dcf    lkj   bgh

为什么不尝试使用
apply
isin
tolist

print(df.apply(lambda x: x[x.isin(ls)].tolist() + x[~x.isin(ls)].tolist(), axis=1))
输出:

  col1 col2 col3
0  ccc  aaa  dfd
1  sge  sdf  jjj
2  fgh  rty  rtg
3  dfg  hji  hyt
4  dcf  lkj  bgh

我只需加载每一行,得到
ls
中的一行,并将其作为第一个值,方法是使用
isin
tolist
+

将其余的行添加到末尾,使其成为第一个值。下面是另一个快速解决方案:

df = pd.DataFrame({'col1':['aaa','sdf','rty','hji','lkj'],
                   'col2':['dfd','jjj','fgh','dfg','bgh'],
                   'col3':['ccc','sge','rtg','hyt','dcf']}) 
list2 = pd.DataFrame({'list':['ccc','sge','fgh','dfg','dcf']})

list2.assign(**df).unstack().drop_duplicates().groupby(level=1).agg(list).apply(pd.Series, index=[1,2,3]).add_prefix('col_')                                                                       

  col_1 col_2 col_3
0   ccc   aaa   dfd
1   sge   sdf   jjj
2   fgh   rty   rtg
3   dfg   hji   hyt
4   dcf   lkj   bgh


起初,我选择@Ben Dickson(以下)给出的解决方案作为最佳答案,但后来我发现运行更大的数据需要很长时间。我尝试使用单一列表理解,我的方法应该更快。检查一下,让我知道!我收到以下错误消息:AttributeError:“DataFrame”对象没有属性“list”。我正在使用python 2。它是相关的吗?@Taie您可以使用
df2[“list”]
instedit给我这个错误消息keyrerror:“list”您的
df2
dataframe是否有一个名为“list”的列?我假设是这样的,如您的示例所示。另外请注意,我已经使用了
df2.list
两次。我收到以下错误消息:TypeError:“type”对象不可编辑。我正在使用python2,我无法让pandas在python2中工作,否则我会尽力帮助。我会看看是否可以让一个虚拟机来测试它,这对我来说是可行的,但我的速度测试表明,这比使用单个apply语句要慢约50%(如我的答案所示)。不过,我还没有测试它的伸缩性。它也相当冗长!我喜欢这个解决方案。简洁典雅:)
  col1 col2 col3
0  ccc  aaa  dfd
1  sge  sdf  jjj
2  fgh  rty  rtg
3  dfg  hji  hyt
4  dcf  lkj  bgh
df = pd.DataFrame({'col1':['aaa','sdf','rty','hji','lkj'],
                   'col2':['dfd','jjj','fgh','dfg','bgh'],
                   'col3':['ccc','sge','rtg','hyt','dcf']}) 
list2 = pd.DataFrame({'list':['ccc','sge','fgh','dfg','dcf']})

list2.assign(**df).unstack().drop_duplicates().groupby(level=1).agg(list).apply(pd.Series, index=[1,2,3]).add_prefix('col_')                                                                       

  col_1 col_2 col_3
0   ccc   aaa   dfd
1   sge   sdf   jjj
2   fgh   rty   rtg
3   dfg   hji   hyt
4   dcf   lkj   bgh