Python 数据帧为每个组重新排序单元格
我有一个由3组组成的数据框架,如:Python 数据帧为每个组重新排序单元格,python,pandas,dataframe,position,Python,Pandas,Dataframe,Position,我有一个由3组组成的数据框架,如: group value1 value2 value3 1 A1 A2 A3 1 B1 B2 B3 1 C1 C2 C3 2 D1 D2 D3 2 E1 E2 E3 2 F1 F2 F3 ... 我想根据一个固定的规则对每组中的单元格按
group value1 value2 value3
1 A1 A2 A3
1 B1 B2 B3
1 C1 C2 C3
2 D1 D2 D3
2 E1 E2 E3
2 F1 F2 F3
...
我想根据一个固定的规则对每组中的单元格按其“位置”进行重新排序,并在所有组中重复相同的操作
此“固定”规则的工作原理如下:
输入:
group value1 value2 value3
1 position1 position2 position3
1 position4 position5 position6
1 position7 position8 position9
输出:
group value1 value2 value3
1 position1 position8 position6
1 position4 position2 position9
1 position7 position5 position3
最终,数据帧应该是这样的(如果这有意义的话):
如果dataframe只有一个组,我知道如何重新排序-基本上创建一个临时变量来存储值,通过.loc获取每个单元格,并用所需的值覆盖每个单元格
然而,即使我们只有1组3行,这仍然是一个明显愚蠢和乏味的方式
我的问题是:我们可能吗
下面是一个建议,它使用numpy索引,并在每个组上进行重塑 设置: 假设您的原始df和位置数据帧如下所示:
d = {'group': [1, 1, 1, 2, 2, 2],
'value1': ['A1', 'B1', 'C1', 'D1', 'E1', 'F1'],
'value2': ['A2', 'B2', 'C2', 'D2', 'E2', 'F2'],
'value3': ['A3', 'B3', 'C3', 'D3', 'E3', 'F3']}
out_d = {'group': [1, 1, 1, 2, 2, 2],
'value1': ['position1', 'position4', 'position7',
'position1', 'position4', 'position7'],
'value2': ['position8', 'position2', 'position5',
'position8', 'position2', 'position5'],
'value3': ['position6', 'position9', 'position3',
'position6', 'position9', 'position3']}
df = pd.DataFrame(d)
out = pd.DataFrame(out_d)
print("Original dataframe :\n\n",df,"\n\n Position dataframe :\n\n",out)
Original dataframe :
group value1 value2 value3
0 1 A1 A2 A3
1 1 B1 B2 B3
2 1 C1 C2 C3
3 2 D1 D2 D3
4 2 E1 E2 E3
5 2 F1 F2 F3
Position dataframe :
group value1 value2 value3
0 1 position1 position8 position6
1 1 position4 position2 position9
2 1 position7 position5 position3
3 2 position1 position8 position6
4 2 position4 position2 position9
5 2 position7 position5 position3
工作解决方案: 方法1::创建函数并在
df.groupby.apply中使用
#remove letters and extract only position numbers and subtract 1
#since python indexing starts at 0
o = out.applymap(lambda x: int(''.join(re.findall('\d+',x)))-1 if type(x)==str else x)
#Merge this output with original dataframe
df1 = df.merge(o,on='group',left_index=True,right_index=True,suffixes=('','_pos'))
# Build a function which rearranges the df based on the position df:
def fun(x):
c = x.columns.str.contains("_pos")
return pd.DataFrame(np.ravel(x.loc[:,~c])[np.ravel(x.loc[:,c])]
.reshape(x.loc[:,~c].shape),
columns=x.columns[~c])
方法2:迭代每个组并重新安排:
o = out.applymap(lambda x: int(''.join(re.findall('\d+',x)))-1 if type(x)==str else x)
df1 = df.merge(o,on='group',left_index=True,right_index=True,
suffixes=('','_pos')).set_index("group")
idx = df1.index.unique()
l = []
for i in idx:
v = df1.loc[i]
c = v.columns.str.contains("_pos")
l.append(np.ravel(v.loc[:,~c])[np.ravel(v.loc[:,c])].reshape(v.loc[:,~c].shape))
final = pd.DataFrame(np.concatenate(l),index=df1.index,
columns=df1.columns[~c]).reset_index()
print(final)
group value1 value2 value3
0 1 A1 C2 B3
1 1 B1 A2 C3
2 1 C1 B2 A3
3 2 D1 F2 E3
4 2 E1 D2 F3
5 2 F1 E2 D3
你已经有输出位置数据框了吗?@anky遗憾的是没有,因为实际输入有数百个单元格,我无法手动调整所有单元格。对不起,我不明白,那么重新排列的逻辑是什么?什么是固定规则?@anky啊,对不起,我的意思含糊不清!规则是从示例输入组到输出的转换,与此完全相同。我想将此应用于许多此类组的数据帧。“否”的意思是我没有实际数据帧的输出。@anky他们有其他名称。位置只是表示位置哇,非常感谢!!让我看一看look@GrumpyCivet当然,很乐意帮忙。让我知道进展如何,尽管这是一个有趣的问题。:)我已经添加了2个解决方案。方法1:除了在步骤“输出=(df1.groupby(“组”)。应用(乐趣)。重置索引(“组”)。重置索引(drop=True))”“有一个错误”值错误:无法将大小为9的数组重塑为形状(3,4)”方法2工作得很好!我仍然在弄清楚这到底是怎么回事。无论如何,非常感谢anky@脾气暴躁的果子狸很高兴,想知道为什么这个方法不起作用。它在我的系统上工作。可能在位置df中有其他列,您可能只希望删除并保留组、值1、值2、值3
output = (df1.groupby("group").apply(fun).reset_index("group")
.reset_index(drop=True))
print(output)
group value1 value2 value3
0 1 A1 C2 B3
1 1 B1 A2 C3
2 1 C1 B2 A3
3 2 D1 F2 E3
4 2 E1 D2 F3
5 2 F1 E2 D3
o = out.applymap(lambda x: int(''.join(re.findall('\d+',x)))-1 if type(x)==str else x)
df1 = df.merge(o,on='group',left_index=True,right_index=True,
suffixes=('','_pos')).set_index("group")
idx = df1.index.unique()
l = []
for i in idx:
v = df1.loc[i]
c = v.columns.str.contains("_pos")
l.append(np.ravel(v.loc[:,~c])[np.ravel(v.loc[:,c])].reshape(v.loc[:,~c].shape))
final = pd.DataFrame(np.concatenate(l),index=df1.index,
columns=df1.columns[~c]).reset_index()
print(final)
group value1 value2 value3
0 1 A1 C2 B3
1 1 B1 A2 C3
2 1 C1 B2 A3
3 2 D1 F2 E3
4 2 E1 D2 F3
5 2 F1 E2 D3