Pandas DataFrame:如何按块进行分组和排序?

3

我正在使用一个包含以下数据的DataFrame进行工作,并以两种不同的方式对数据进行分组。

>>> d = {
     "A": [100]*7 + [200]*7,
     "B": ["one"]*4 + ["two"]*3 + ["one"]*3 + ["two"]*4,
     "C": ["foo"]*3 + ["bar"] + ["foo"] + ["bar"]*2 + ["foo"]*2 + ["bar"] + ["foo"]*3 + ["bar"],
     "D": ["yay"] + ["nay"]*2 + ["yay"] + ["nay"]*3 + ["yay"] + ["nay"] + ["yay"]*3 + ["nay"] + ["yay"],
     "X": [2, 8, 3, 5, 1, 4, 3, 2, 6, 5, 1, 2, 4, 7]
    }

>>> df = pd.DataFrame(d)
>>> df

     A    B    C    D    X
0  100  one  foo  yay    2
1  100  one  foo  nay    8
2  100  one  foo  nay    3
3  100  one  bar  yay    5
4  100  two  foo  nay    1
5  100  two  bar  nay    4
6  100  two  bar  nay    3
7  200  one  foo  yay    2
8  200  one  foo  nay    6
9  200  one  bar  yay    5
10 200  two  foo  yay    1
11 200  two  foo  yay    2
12 200  two  foo  nay    4
13 200  two  bar  yay    7

>>> df_grp = df.groupby(['A', 'B'])
>>> df_grp_sorted = df_grp.sum().sort_values('X', ascending = False)
>>> df_grp_long = df.groupby(['A', 'B', 'C', 'D'])
>>> df_grp_sorted_long = df_grp_long.sum().sort_values('X', ascending = False)

这给我们带来了:
>>> df_grp_sorted

            X
100  one   18
200  two   14
     one   13
100  two    8


>>> df_grp_sorted_long

                      X
100  one  foo  nay   11
     two  bar  nay    7
200  two  bar  yay    7
     one  foo  nay    6
100  one  bar  yay    5
200  one  bar  yay    5
     two  foo  nay    4
               yay    3
100  one  foo  yay    2
200  one  foo  yay    2    
100  two  foo  nay    1

现在,我想从df_grp_sorted_long中获取详细信息,并按照df_grp_sorted的结构进行排列。如下:

>>> df_result

                      X
100  one  foo  nay   11
               yay    5
          foo  yay    2
200  two  bar  yay    7
          foo  nay    4
               yay    3
     one  foo  nay    6
          bar  yay    5
          foo  yay    2    
100  two  bar  nay    7
          foo  nay    1
          

我已经使用以下代码完成了此操作(这与此帖子的建议相反):
>>> col_names = ['A', 'B', 'C', 'D']
>>> df_result = pd.DataFrame(columns=col_names)
>>> for (i, (a, b)) in enumerate(df_grp_sorted.index):
        df_result = pd.concat(
            (
                df_result,
                (df[(df['A']==a) & (df['B']==b)]
                .groupby(col_names)
                .sum()
                .sort_values('X', ascending=False)
                )
            )
        )
>>> df_result = df_result["X"]

这个方法可以得出正确的答案,但对于大型数据集来说速度非常慢。我还想知道是否有一种固有的方式来进行分组/排序的组合。

另外,也许这种方法不是正确的方法,存在更简单的方法来获得等效的结果吗?

1个回答

1
另一种方法是合并这两个框架。使用您提供的内容,可以进行以下操作:
import pandas as pd

d = {"A": [100] * 7 + [200] * 7,
     "B": ["one"] * 4 + ["two"] * 3 + ["one"] * 3 + ["two"] * 4,
     "C": ["foo"] * 3 + ["bar"] + ["foo"] + ["bar"] * 2 + ["foo"] * 2 + ["bar"] + ["foo"] * 3 + ["bar"],
     "D": ["yay"] + ["nay"] * 2 + ["yay"] + ["nay"] * 3 + ["yay"] + ["nay"] + ["yay"] * 3 + ["nay"] + ["yay"],
     "X": [2, 8, 3, 5, 1, 4, 3, 2, 6, 5, 1, 2, 4, 7]}

df = pd.DataFrame(data=d)
df_grp_sorted = df.groupby(["A", "B"], as_index=False).sum().sort_values("X", ascending=False)
df_grp_long = df.groupby(["A", "B", "C", "D"], as_index=False)
df_grp_sorted_long = df_grp_long.sum().sort_values("X", ascending=False)
df_result = (df_grp_sorted
             .merge(df_grp_sorted_long, how="outer", on=["A", 'B'])
             .drop(columns=["X_x"])
             .rename(columns={"X_y": "X"}))

输出

A B C D X
100 foo nay 11
100 bar yay 5
100 foo yay 2
200 bar yay 7
200 foo nay 4
200 foo yay 3
200 foo nay 6
200 bar yay 5
200 foo yay 2
100 bar nay 7
100 foo nay 1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接