Python 将多列合并为一列
我有一个df,它有多个以相同值结尾的列。我想把这些列合并成最后一列。例如,任何以“_1”结尾的列都应该进入标记为“final_1”的新列。如果“_1”中的所有值均为“1”,则final_1中的值将为1;否则,如果“_1”列中至少有一个值不是“1”,则final_1中的值将为0 如果我的解释不正确,那么原始和最终结果数据帧将更加清晰Python 将多列合并为一列,python,pandas,pandas-groupby,Python,Pandas,Pandas Groupby,我有一个df,它有多个以相同值结尾的列。我想把这些列合并成最后一列。例如,任何以“_1”结尾的列都应该进入标记为“final_1”的新列。如果“_1”中的所有值均为“1”,则final_1中的值将为1;否则,如果“_1”列中至少有一个值不是“1”,则final_1中的值将为0 如果我的解释不正确,那么原始和最终结果数据帧将更加清晰 df = pd.DataFrame({'KEY': ['100000003', '100000009', '100000009', '100000009'],
df = pd.DataFrame({'KEY': ['100000003', '100000009', '100000009', '100000009'],
'RO_1': [1, 1, 4,1],
'RO_2': [1, 0, 0,0],
'RO_3': [1, 1, 1,1],
'en_1': [1, 4, 1,1],
'en_2': [1, 4, 1,0],
'en_3': [1, 4, 4,0],
'ao_1': [1, 4, 1,1],
'ao_2': [1, 4, 1,0],
'ao_3': [1, 4, 4,0] })
KEY RO_1 RO_2 RO_3 ao_1 ao_2 ao_3 en_1 en_2 en_3
0 100000003 1 1 1 1 1 1 1 1 1
2 100000009 4 0 1 1 1 4 1 1 4
3 100000009 1 0 1 1 0 0 1 0 0
最终结果:
KEY RO_1 RO_2 RO_3 ao_1 ao_2 ao_3 en_1 en_2 en_3 Final1 Final2 Final3
0 100000003 1 1 1 1 1 1 1 1 1 1 1 1
2 100000009 4 0 1 1 1 4 1 1 4 0 0 0
3 100000009 1 0 1 1 0 0 1 0 0 1 0 0
我目前的尝试。因为有3个不同的列,所以我使用循环。然后,我将原始df与新帧(mc)相结合。但是我没有得到任何不同
for i in range(1,4):
mc = df.filter(regex='^_' + str(i)).isin([1]).astype(int).rename(columns=lambda x: x.replace('_', 'Final'))
df= pd.concat([df, mc], axis=1)
@DSM提出了一个更好的拆分列名的选项:
In [170]: cols = df.columns.drop('KEY')
In [171]: d = (df[cols]
.groupby(cols.str.split('_').str[-1], axis=1)
.all()
.astype(int)
.add_prefix('Final_'))
In [172]: df.join(d)
Out[172]:
KEY RO_1 RO_2 RO_3 ao_1 ao_2 ao_3 en_1 en_2 en_3 Final_1 Final_2 Final_3
0 100000003 1 1 1 1 1 1 1 1 1 1 1 1
1 100000009 1 0 1 4 4 4 4 4 4 1 0 1
2 100000009 4 0 1 1 1 4 1 1 4 1 0 1
3 100000009 1 0 1 1 0 0 1 0 0 1 0 0
或来自(c)@DSM和@piRSquared的该溶液:
In [194]: df.join(df.drop('KEY', 1)
.eq(1)
.groupby(lambda c: c.rsplit('_', 1)[1], 1)
.all().astype(int).add_prefix('Final'))
Out[194]:
KEY RO_1 RO_2 RO_3 ao_1 ao_2 ao_3 en_1 en_2 en_3 Final1 Final2 Final3
0 100000003 1 1 1 1 1 1 1 1 1 1 1 1
1 100000009 1 0 1 4 4 4 4 4 4 0 0 0
2 100000009 4 0 1 1 1 4 1 1 4 0 0 0
3 100000009 1 0 1 1 0 0 1 0 0 1 0 0
如果您的结构是预定义的,则
numpy
提供了一个有效的解决方案:
n = 3
v = df.iloc[:,1:].values
v[v!=1] = 0
for i in range(1, n+1):
df['Final'+str(i)] = (np.all(v[:, [i-1+n*k for k in range(n)]], axis=1)).astype(int)
# KEY RO_1 RO_2 RO_3 ao_1 ao_2 ao_3 en_1 en_2 en_3 Final1 \
# 0 100000003 1 1 1 1 1 1 1 1 1 1
# 1 100000009 1 0 1 4 4 4 4 4 4 0
# 2 100000009 4 0 1 1 1 4 1 1 4 0
# 3 100000009 1 0 1 1 0 0 1 0 0 1
# Final2 Final3
# 0 1 1
# 1 0 0
# 2 0 0
# 3 0 0
比较他想要的输出和他的代码,我认为OP更多的是在
(d==1).groupby(d.columns.str.split('''').str[-1],axis=1).all().astype(int)
(通常我避免使用正则表达式,因为我不喜欢它们。:-)还可以使用应用于索引的lambda
df.join(df.drop('KEY',1.).groupby(lambda c:c.rsplit('u',1)[1],1]).all().astype(int).add_prefix('Final'))
更重要的一点是,我解释他的“如果''u 1'中的所有值都是'1',那么他将是1”,而.isin([1])
的意思是=1
。将他的期望值与您的值进行比较:他有一行0。@DSM您是否建议df.join(df.drop('KEY',1.).eq(1).groupby(lambda c:c.rsplit('u',1)[1],1.).all().astype(int).添加_前缀('Final')
@DSM您正确解释了吗。我离开.isin()只是想看看多个条件的解决方案,但按照我提问的方式,您的回答是准确的。