我有一个数据框(熊猫):
import pandas as pd
df = pd.DataFrame({'A': ['x1', 'x2', 'x3', 'x4'],
'B': ['b', 'b', 'c', 'c'],
'C': ['d', 'd', 'e', 'e'],
'D': ['x', 'y', 'y', 'x'],})
我要合并A中的值唯一的所有列的值。
ouput = pd.DataFrame({'A': ['x1', 'x2', 'x3', 'x4'],
'BC': ['bd', 'bd', 'ce', 'ce'],
'D': ['x', 'y', 'y', 'x'],})
最好有一个与列名B,C无关的解决方案(也许还有更多带有此“冗余信息”的列)。 A的列名是已知的。
鉴于我的初始数据帧是:
df = pd.DataFrame({'A': ['x1', 'x2', 'x3', 'x4'],
'B': ['b', 'b', 'c', 'c'],
'C': ['d', 'd', 'd', 'e'],
'D': ['x', 'y', 'y', 'x'],})
所需的输出是初始df(不变):
df = pd.DataFrame({'A': ['x1', 'x2', 'x3', 'x4'],
'B': ['b', 'b', 'c', 'c'],
'C': ['d', 'd', 'd', 'e'],
'D': ['x', 'y', 'y', 'x'],})
非常感谢!
完整的解决方案(感谢比利时人罗比):
import pandas as pd
df = pd.DataFrame({'A': ['x1', 'x2', 'x3', 'x4'],
'B': ['b', 'b', 'c', 'c'],
'C': ['d', 'd', 'e', 'e'],
'D': ['x', 'y', 'y', 'x']})
print(df)
def is_redundant(df, A, B):
#remove column a
A=A
B=B
if len(df.groupby(f'{A}')) == len(df.groupby([f'{A}', f'{B}'])):
return True
else:
return False
def drop_redundant(df, redundant_groups):
list=redundant_groups
for i in list:
if len(df.groupby(f'{i[0]}')) == len(df.groupby([f'{i[0]}', f'{i[1]}'])):
df[f'{i[0]}' + f'{i[1]}'] = df[[f'{i[0]}', f'{i[1]}']].sum(axis=1)
df.drop([f'{i[0]}', f'{i[1]}'], axis=1, inplace=True)
return(df)
else:
return(df)
cols = [c for c in df.columns if c != 'A']
redundant_groups = []
idx_left = 0
while idx_left < len(cols)-1:
new_group = []
idx_right = idx_left+1
while idx_right < len(cols):
if is_redundant(df, cols[idx_left], cols[idx_right]):
new_group.append(cols.pop(idx_right))
else:
idx_right += 1
if new_group:
redundant_groups.append(new_group + [cols[idx_left]])
idx_left += 1
print(redundant_groups)
drop_redundant(df, redundant_groups)
print(df)
输出:
A B C D
0 x1 b d x
1 x2 b d y
2 x3 c e y
3 x4 c e x
[['C', 'B']]
A D CB
0 x1 x db
1 x2 y db
2 x3 y ec
3 x4 x ec
[Finished in 0.837s]
答案 0 :(得分:0)
比较列'B'
和'C'
是否为“冗余”:
len(df.groupby('B')) == len(df.groupby(['B', 'C'])
这将检查是否将'C'
添加到分组标签中,而不是仅按'B'
进行分组。
然后,您可以轻松地在df.columns
中的所有标签对上运行此标签(确保不包含'A'
)。
如果发现两列具有冗余信息,则可以使用:
df['B' + 'C'] = df[['B', 'C']].sum(axis=1)
df.drop(['B', 'C'], axis=1, inplace=True)
以合并的信息替换它们。
如果您想在双循环中使用它(检查所有成对的列),则必须小心,因为您可能有3个都包含相同信息的列(例如B,C和F) ),并且在处理完B和C之后,您将尝试比较B和F-但B列不再存在。
为解决这个问题,我可能首先尝试构建一个所有冗余对的列表。假设我们有一个“ is_redundant(df, c1, c2)
”功能(使用上面的行进行比较)。
cols = [c for c in df.columns if c != 'A']
redundant_groups = []
idx_left = 0
while idx_left < len(cols)-1:
new_group = []
idx_right = idx_left+1
while idx_right < len(cols):
if is_redundant(df, cols[idx_left], cols[idx_right]):
new_group.append(cols.pop(idx_right))
else:
idx_right += 1
if new_group:
redundant_groups.append(new_group + [cols[idx_left]])
idx_left += 1
这将创建一组相互冗余的列。
之后,您可以轻松地修改以上组合代码以一次处理多个列。