Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/288.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 数据帧为每个组重新排序单元格_Python_Pandas_Dataframe_Position - Fatal编程技术网

Python 数据帧为每个组重新排序单元格

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 ... 我想根据一个固定的规则对每组中的单元格按

我有一个由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       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