将 DataFrame 列分组为 MultiIndex 的功能方法

Posted

技术标签:

【中文标题】将 DataFrame 列分组为 MultiIndex 的功能方法【英文标题】:Functional approach to group DataFrame columns into MultiIndex 【发布时间】:2022-01-14 14:45:09 【问题描述】:

有没有更简单的功能方法将列分组到 MultiIndex 中?

# Setup
l = [...]
l2,l3,l4 = do_things(l, [2,3,4])
d = 2:l2, 3:l3, 4:l4
# Or,
l = l2 = l3 = l4 = list(range(20))

我的方法存在问题:

# Cons:
# * Complicated
# * Requires multiple iterations over the dictionary to occur
#   in the same order. This is guaranteed as the dictionary is
#   unchanged but I'm not happy with the implicit dependency.
df = pd.DataFrame\
    ( zip(*d.values())
    , index=l
    , columns=pd.MultiIndex.from_product([["group"], d.keys()])
    ).rename_axis("x").reset_index().reset_index()

# Cons:
# * Complicated
# * Multiple assignments
df = pd.DataFrame(d, index=l).rename_axis("x")
df.columns = pd.MultiIndex.from_product([["group"],df.columns])
df = df.reset_index().reset_index()

我正在寻找类似的东西:

df =\
    ( pd.DataFrame(d, index=l)
    . rename_axis("x")
    . group_columns("group")
    . reset_index().reset_index()
    )

结果:

   index  x group
                2  3  4
0      0  2     0  0  0
1      1  2     0  0  0
2      2  2     0  0  0
3      3  2     0  0  0
4      4  1     0  0  0
5      5  2     0  0  0
6      6  1     0  0  0
7      7  2     0  0  0
8      8  4     0  1  1
9      9  4     0  1  1
10    10  4     0  1  1
11    11  0     0  1  1
12    12  1     0  1  1
13    13  1     0  1  1
14    14  3     1  2  2
15    15  1     1  2  2
16    16  1     1  2  3
17    17  1     1  2  3
18    18  4     1  2  3
19    19  3     1  2  3
20    20  4     1  2  3
21    21  4     1  2  3
22    22  4     1  2  3
23    23  4     1  2  3

【问题讨论】:

也许只是直接从字典和l 构建DataFrame? df = pd.DataFrame(('index', ''): pd.RangeIndex(len(l)), ('x', ''): l | ('group', k): v for k, v in d.items())? 那将是一个很好的答案。我会用reset_index() 替换第一个条目“index”。你认为 dict union 比 **expansion 更清晰吗?我会保留它以获取其他答案。 我认为这两种方式都没有区别。这正是我开始的方式,因为在您进行编辑之前我不太确定输出应该是什么。 【参考方案1】:

重新格式化字典并将其传递给 DataFrame 构造函数可能是最简单的:

# Sample Data
size = 5
lst = np.arange(size) + 10
d = 2: lst, 3: lst + size, 4: lst + (size * 2)

df = pd.DataFrame(
    # Add group level by changing keys to tuples
    ('group', k): v for k, v in d.items(),
    index=lst
)

输出:

   group        
       2   3   4
10    10  15  20
11    11  16  21
12    12  17  22
13    13  18  23
14    14  19  24

请注意,元组会自动解释为 MultiIndex


这之后可以进行任何所需的操作链:

df = pd.DataFrame(
    ('group', k): v for k, v in d.items(),
    index=lst
).rename_axis('x').reset_index().reset_index()

df:

  index   x group        
                2   3   4
0     0  10    10  15  20
1     1  11    11  16  21
2     2  12    12  17  22
3     3  13    13  18  23
4     4  14    14  19  24

也可以合并步骤,直接生成完整的DataFrame:

df = pd.DataFrame(
    ('index', ''): pd.RangeIndex(len(lst)),
    ('x', ''): lst,
    **('group', k): v for k, v in d.items()
)

df:

  index   x group        
                2   3   4
0     0  10    10  15  20
1     1  11    11  16  21
2     2  12    12  17  22
3     3  13    13  18  23
4     4  14    14  19  24

当然可以使用字典理解和熊猫操作的任意组合。

【讨论】:

以上是关于将 DataFrame 列分组为 MultiIndex 的功能方法的主要内容,如果未能解决你的问题,请参考以下文章

Python pandas:使用方法链接将列添加到分组的 DataFrame

如何使用索引标签将 DataFrame 分组并执行操作以根据每个索引在特定列中找到 3 个最大的

使用 Python,如何按小时对 Dataframe 中的列进行分组?

将 pyspark groupedData 转换为 pandas DataFrame

获取由 PySpark Dataframe 上的另一列分组的列的不同元素

Altair - 如何在不操作 DataFrame 的情况下创建分组条形图