python 熊猫通过删除重复项加入动态列
python panda join dynamic columns by removing duplicates
我们有一个用例,我们需要通过移除存储在熊猫数据框中的 duplicates.Data 来连接一行中的所有列值。
例如,考虑下面的数据框 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: '>=' not supported between instances of 'str' and 'int'
请注意,df 实际上是多核并行任务的一部分。所以如果建议排除并行就太好了。
尝试
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
Returns
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:如果您在任何列中都有 nan
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
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
])
我们有一个用例,我们需要通过移除存储在熊猫数据框中的 duplicates.Data 来连接一行中的所有列值。 例如,考虑下面的数据框 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: '>=' not supported between instances of 'str' and 'int'
请注意,df 实际上是多核并行任务的一部分。所以如果建议排除并行就太好了。
尝试
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
Returns
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:如果您在任何列中都有 nan
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
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
])