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