首页 > 解决方案 > 使用 For 循环对 Pandas DataFrame 进行排序和重新排列

问题描述

我有一个下面的数据框

df = pd.DataFrame([['NY','R',1],
                  ['NJ','Y',12],
                  ['FL','B',20],
                  ['CA','B',40],
                  ['AZ','Y',51],
                  ['NY','R',2],
                  ['NJ','Y',18],
                  ['FL','B',30],
                  ['CA','B',20],
                  ['AZ','Y',45],
                  ['NY','Y',3],
                  ['NJ','R',15],
                  ['FL','R',10],
                  ['CA','R',70],
                  ['AZ','B',25],
                  ['NY','B',4],
                  ['NJ','B',17],
                  ['FL','Y',30],
                  ['CA','R',30],
                  ['AZ','B',75],
                  ['FL','R',5],
                  ['FL','Y',25],
                  ['NJ','R',14],
                  ['NJ','B',11],
                  ['NY','B',5],
                  ['NY','Y',7]],
                    columns = ['State', 'ID','data'])


State ID  data
0     NY  R     1
1     NJ  Y    12
2     FL  B    20
3     CA  B    40
4     AZ  Y    51
5     NY  R     2
6     NJ  Y    18
7     FL  B    30
8     CA  B    20
9     AZ  Y    45
10    NY  Y     3
11    NJ  R    15
12    FL  R    10
13    CA  R    70
14    AZ  B    25
15    NY  B     4
16    NJ  B    17
17    FL  Y    30
18    CA  R    30
19    AZ  B    75
20    FL  R     5
21    FL  Y    25
22    NJ  R    14
23    NJ  B    11
24    NY  B     5
25    NY  Y     7

我想要做的:重新创建一个新的数据框,使其仅包含来自每个状态的最小数字。例如:对于州:NY 和 ID:R,有 2 个数据:1 和 2。对于类别 State:NY 和 ID:R,新数据帧将只取值:1。新数据帧最好如下所示:

  State  dataR  dataB  dataY
0    NY    1.0      4    3.0
1    NJ   14.0     11   12.0
2    FL    5.0     20   25.0
3    CA   30.0     20    NaN
4    AZ    NaN     25   45.0

请注意:状态 AZ 和 CA 在结果中分别没有列 dataR 和 dataY 的任何值 (NaN),因为它们在原始数据框中最初没有这样的值。另请注意,结果中的列变为 dataR、dataB 和 dataY。我的目标是在结果中创建这些列,以便以后可以在实际数据中轻松读取结果。

并且:我还希望灵活,以便我可以在每个 ID R&Y 和 B 的数据中寻找每个州的最小值,因此新的数据框将如下所示:

  State  dataRY  dataB
0    NY       1      4
1    NJ      12     11
2    FL       5     20
3    CA      30     20
4    AZ      45     25

我尝试使用 for 循环如下:

colours = [['R'],['B'],['Y']]

def rearranging(df):
    df_result = []
    for c in colours:
        df_colours          = df[df['ID'].isin(c)]
        df_colours_result   = []
        for state in np.unique(df['State'].values):
            df1     = df_colours[df_colours['State'] == state]
            df2     = df1.nsmallest(1,'data')
            df_colours_result.append(df2)
        first_loop_result = pd.concat(df_colours_result,ignore_index = True, sort = False)
        df_result.append(first_loop_result)
    final_result = pd.concat(df_result, axis = 1)
    return final_result

变量颜色应该在那里,因为我想要灵活并且如果数据源稍后发生更改,我可以更改它们的值。

上述for循环的结果是:

  State   ID  data State ID  data State   ID  data
0    CA    R  30.0    AZ  B    25    AZ    Y  45.0
1    FL    R   5.0    CA  B    20    FL    Y  25.0
2    NJ    R  14.0    FL  B    20    NJ    Y  12.0
3    NY    R   1.0    NJ  B    11    NY    Y   3.0
4   NaN  NaN   NaN    NY  B     4   NaN  NaN   NaN

我不喜欢我的结果,因为:很难阅读,我需要重新排列和重命名列。反正有没有通过使用 for 循环来获得我实际上针对上述内容的结果?也欢迎矢量化。

另请注意(再次)我也希望在列 ID 上保持灵活。这就是我要包括的原因,例如我想说我需要查看 ID R&Y 组合和 ID B 的每个州的数据的最小值。在我的尝试中,我只需更改以下代码,循环保持不变:

colours = [['R','Y'],['B']]


结果是:

  State ID  data State ID  data
0    AZ  Y    45    AZ  B    25
1    CA  R    30    CA  B    20
2    FL  R     5    FL  B    20
3    NJ  Y    12    NJ  B    11
4    NY  R     1    NY  B     4

注意:相比之下,如果存在 NaN,那么 NaN 会被简单地忽略(并且不被视为零)。

再一次,结果与我的目标不一样,而且这张表的信息量不够。

标签: pythonpandasdataframefor-loopautomation

解决方案


IIUC,使用groupby()onStateIDget minof datacolumn,add_prefix如果需要,还可以使用 unstack()。:

df.groupby(['State','ID'],sort=False)['data'].min().unstack().add_prefix('data_')

ID     data_R  data_Y  data_B
State                        
NY        1.0     3.0     4.0
NJ       14.0    12.0    11.0
FL        5.0    25.0    20.0
CA       30.0     NaN    20.0
AZ        NaN    45.0    25.0

编辑:根据 OP 的要求,如果您想合并YR在一起,只需替换并执行类似操作:

(df.assign(ID=df['ID'].replace(['Y','R'],'YR'))
    .groupby(['State','ID'],sort=False)['data'].min().unstack().add_prefix('data_'))

ID     data_YR  data_B
State                 
NY           1       4
NJ          12      11
FL           5      20
CA          30      20
AZ          45      25

推荐阅读