我们有一个用例,我们需要通过删除duplicates来连接行中的所有列值.Data存储在panda的数据框中。 例如,考虑下面的数据帧df,列A,B,C
A B C
X1 AX X1
X2 X2 X1
X3 X3 X3
X4 XX XX
我想添加一个新列,它将A到B连接到C,如果通过保留订单找到重复项,则删除重复项。输出就像
A B C Newcol
X1 AX X1 X1_AX
X2 X2 X1 X2_X1
X3 X3 X3 X3
X4 XX XX X4_XX
请注意,列数是动态的。 截至目前,我正在使用命令
df.apply(lambda x: '-'.join(x.dropna().astype(str).drop_duplicates()),axis=1)
但这非常慢,我的数据大约需要150秒。 但由于90%的数据框通常只有2列,我在我的代码中放了一个if语句,并为2列的情况运行以下命令
t1=pd.Series(np.where(df.iloc[:,0].dropna().astype(str) != df.iloc[:,1].dropna().astype(str), df.iloc[:,0].dropna().astype(str)+"-"+df.iloc[:,1].dropna().astype(str),df.iloc[:,1].dropna().astype(str)))
需要大约55.3毫秒
甚至
t1=df.iloc[:,0].dropna().astype(str).where(df.iloc[:,0].dropna().astype(str) == df.iloc[:,1].dropna().astype(str), df.iloc[:,0].dropna().astype(str)+"-"+df.iloc[:,1].dropna().astype(str))
两者消耗几乎相同的时间(55毫秒而不是150秒),但问题是它仅适用于2列。 我想创建一个通用语句,以便它可以处理n个列。 我尝试在顶部使用reduce,但是当我尝试使用3列时它出错了。
reduce((lambda x,y:pd.Series(np.where(df.iloc[:,x].dropna().astype(str) != df.iloc[:,y].dropna().astype(str), df.iloc[:,x].dropna().astype(str)+"-"+df.iloc[:,y].dropna().astype(str),df.iloc[:,y].dropna().astype(str)))),list(range(df.shape[1])))
TypeError:'>''在'str'和'int'
的实例之间不受支持
请注意,df实际上是多核并行任务的一部分。如果这些建议排除了并行性,那将会很棒。
答案 0 :(得分:3)
尝试
df['new'] = df.astype('str').apply(lambda x: '_'.join(set(x)), axis = 1)
A B C new
0 X1 AX X1 AX_X1
1 X2 X2 X1 X1_X2
2 X3 X3 X3 X3
3 X4 XX XX X4_XX
编辑:维护列值的顺序
def my_append(x):
l = []
for elm in x:
if elm not in l:
l.append(elm)
return '_'.join(l)
df['New col']=df.astype('str').apply(my_append, axis = 1)
1000 loops, best of 3: 871 µs per loop
返回
A B C New col
0 X1 AX X1 X1_AX
1 X2 X2 X1 X2_X1
2 X3 X3 X3 X3
3 X4 XX XX X4_XX
编辑1:如果您在任何列中都有像这样的
A B C
0 X1 AX X1
1 X2 X2 X1
2 X3 X3 X3
3 NaN XX XX
处理该函数,然后应用
def my_append(x):
l = []
for elm in x:
if elm not in l:
l.append(elm)
l = [x for x in l if str(x) != 'nan']
return '_'.join(l)
df['New col']=df.astype('str').apply(my_append, axis = 1)
A B C New col
0 X1 AX X1 X1_AX
1 X2 X2 X1 X2_X1
2 X3 X3 X3 X3
3 NaN XX XX XX
答案 1 :(得分:1)
pd.unique
没有排序。使用它包含在理解
df.assign(new_col=['_'.join(pd.unique(row)) for row in df.values])
A B C new_col
0 X1 AX X1 X1_AX
1 X2 X2 X1 X2_X1
2 X3 X3 X3 X3
3 X4 XX XX X4_XX
处理NaN
df.assing(new_col=[
'_'.join(pd.unique([i for i in row if pd.notnull(i)])) for row in df.values
])