如何旋转数据框?

发布于 2025-01-15 13:18:44 字数 5675 浏览 1 评论 0原文

  • 什么是枢轴?
  • 我如何旋转?
  • 长格式到宽格式?

我见过很多关于数据透视表的问题,即使他们不知道。编写一个规范的几乎是不可能的问题和答案涵盖了旋转的所有方面...但我要尝试一下。


现有问题和答案的问题在于,问题通常集中在OP难以概括的细微差别上,以便使用许多现有的好的答案。然而,没有一个答案试图给出全面的解释(因为这是一项艰巨的任务)。看一下我的 Google 搜索

  1. 如何在 Pandas 中旋转数据框? - 很好的问题和答案。但答案只回答了具体问题,几乎没有解释。
  2. pandas 数据透视表到数据框 - OP 关注数据透视表的输出,即列的外观。 OP 希望它看起来像 R。这对于 pandas 用户来说不是很有帮助。
  3. pandas 旋转数据框,重复行 - 另一个不错的问题,但答案集中在一种方法上,即 pd.DataFrame .pivot

设置

我明确地命名了我的列和相关列值,以与我将如何在下面的答案中进行透视相对应。

import numpy as np
import pandas as pd
from numpy.core.defchararray import add

np.random.seed([3,1415])
n = 20

cols = np.array(['key', 'row', 'item', 'col'])
arr1 = (np.random.randint(5, size=(n, 4)) // [2, 1, 2, 1]).astype(str)

df = pd.DataFrame(
    add(cols, arr1), columns=cols
).join(
    pd.DataFrame(np.random.rand(n, 2).round(2)).add_prefix('val')
)
print(df)
     key   row   item   col  val0  val1
0   key0  row3  item1  col3  0.81  0.04
1   key1  row2  item1  col2  0.44  0.07
2   key1  row0  item1  col0  0.77  0.01
3   key0  row4  item0  col2  0.15  0.59
4   key1  row0  item2  col1  0.81  0.64
5   key1  row2  item2  col4  0.13  0.88
6   key2  row4  item1  col3  0.88  0.39
7   key1  row4  item1  col1  0.10  0.07
8   key1  row0  item2  col4  0.65  0.02
9   key1  row2  item0  col2  0.35  0.61
10  key2  row0  item2  col1  0.40  0.85
11  key2  row4  item1  col2  0.64  0.25
12  key0  row2  item2  col3  0.50  0.44
13  key0  row4  item1  col4  0.24  0.46
14  key1  row3  item2  col3  0.28  0.11
15  key0  row3  item1  col1  0.31  0.23
16  key0  row0  item2  col3  0.86  0.01
17  key0  row4  item0  col3  0.64  0.21
18  key2  row2  item2  col0  0.13  0.45
19  key0  row2  item0  col4  0.37  0.70

问题

  1. 为什么我会收到ValueError:索引包含重复条目,无法重塑

  2. 如何对 df 进行透视,使 col 值是列,row 值是索引,以及 val0 的平均值 是值吗?

    <前><代码>col col0 col1 col2 col3 col4 排 行 0 0.77 0.605 南 0.860 0.65 第 2 行 0.13 南 0.395 0.500 0.25 第 3 行 南 0.310 南 0.545 南 第 4 行 南 0.100 0.395 0.760 0.24
  3. 如何使缺失值为 0

    col col0 col1 col2 col3 col4
    排
    第 0 行 0.77 0.605 0.000 0.860 0.65
    第2行 0.13 0.000 0.395 0.500 0.25
    第3行 0.00 0.310 0.000 0.545 0.00
    第4行 0.00 0.100 0.395 0.760 0.24
    
  4. 我可以得到除mean以外的东西,比如sum吗?

    col col0 col1 col2 col3 col4
    排
    第 0 行 0.77 1.21 0.00 0.86 0.65
    第2行 0.13 0.00 0.79 0.50 0.50
    第三行 0.00 0.31 0.00 1.09 0.00
    第4行 0.00 0.10 0.79 1.52 0.24
    
  5. 我可以一次进行多个聚合吗?

     总和平均值
    科尔 科尔0 科尔1 科尔2 科尔3 科尔4 科尔0 科尔1 科尔2 科尔3 科尔4
    排
    行0 0.77 1.21 0.00 0.86 0.65 0.77 0.605 0.000 0.860 0.65
    第2行 0.13 0.00 0.79 0.50 0.50 0.13 0.000 0.395 0.500 0.25
    第三行 0.00 0.31 0.00 1.09 0.00 0.00 0.310 0.000 0.545 0.00
    第4行 0.00 0.10 0.79 1.52 0.24 0.00 0.100 0.395 0.760 0.24
    
  6. 我可以聚合多个值列吗?

    <前><代码> val0 val1 科尔 科尔0 科尔1 科尔2 科尔3 科尔4 科尔0 科尔1 科尔2 科尔3 科尔4 排 行0 0.77 0.605 0.000 0.860 0.65 0.01 0.745 0.00 0.010 0.02 第2行 0.13 0.000 0.395 0.500 0.25 0.45 0.000 0.34 0.440 0.79 第三行 0.00 0.310 0.000 0.545 0.00 0.00 0.230 0.00 0.075 0.00 第4行 0.00 0.100 0.395 0.760 0.24 0.00 0.070 0.42 0.300 0.46
  7. 我可以细分多列吗?

    项目 项目0 项目1 项目2
    科尔 科尔2 科尔3 科尔4 科尔0 科尔1 科尔2 科尔3 科尔4 科尔0 科尔1 科尔3 科尔4
    排
    行0 0.00 0.00 0.00 0.77 0.00 0.00 0.00 0.00 0.00 0.605 0.86 0.65
    第2行 0.35 0.00 0.37 0.00 0.00 0.44 0.00 0.00 0.13 0.000 0.50 0.13
    第三行 0.00 0.00 0.00 0.00 0.31 0.00 0.81 0.00 0.00 0.000 0.28 0.00
    第4行 0.15 0.64 0.00 0.00 0.10 0.64 0.88 0.24 0.00 0.000 0.00 0.00
    
  8. 或者

    项目 项目0 项目1 项目2
    科尔 科尔2 科尔3 科尔4 科尔0 科尔1 科尔2 科尔3 科尔4 科尔0 科尔1 科尔3 科尔4
    关键行
    键0行0 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.86 0.00
         第2行 0.00 0.00 0.37 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.50 0.00
         第三行 0.00 0.00 0.00 0.00 0.31 0.00 0.81 0.00 0.00 0.00 0.00 0.00
         第4行 0.15 0.64 0.00 0.00 0.00 0.00 0.00 0.24 0.00 0.00 0.00 0.00
    键1行0 0.00 0.00 0.00 0.77 0.00 0.00 0.00 0.00 0.00 0.81 0.00 0.65
         第2行 0.35 0.00 0.00 0.00 0.00 0.44 0.00 0.00 0.00 0.00 0.00 0.13
         第三行 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.28 0.00
         第4行 0.00 0.00 0.00 0.00 0.10 0.00 0.00 0.00 0.00 0.00 0.00 0.00
    键2行0 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.40 0.00 0.00
         第2行 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.13 0.00 0.00 0.00
         第4行 0.00 0.00 0.00 0.00 0.00 0.64 0.88 0.00 0.00 0.00 0.00 0.00
    
  9. 我可以聚合列和行一起出现的频率,也称为“交叉制表”吗?

    col col0 col1 col2 col3 col4
    排
    行0 1 2 0 1 1
    第2行 1 0 2 1 2
    行3 0 1 0 2 0
    第4行0 1 2 2 1
    
  10. 如何通过仅旋转两列将 DataFrame 从长转换为宽?鉴于,

    np.random.seed([3, 1415])
    df2 = pd.DataFrame({'A': 列表('aaaabbbc'), 'B': np.random.choice(15, 8)})
    df2
       AB
    0个0
    1个11
    2个2
    3个11
    4 乙 10
    5 乙 10
    6 乙 14
    7c 7
    

    预期应该类似于

    <前><代码> abc 0 0.0 10.0 7.0 1 11.0 10.0 南 2 2.0 14.0 南 3 11.0 南 南
  11. 如何在pivot之后将多个索引展平为单个索引?

    来自

    <前><代码> 1 2 1 1 2 2 1 1 b 2 1 0 1 0 0

    <前><代码> 1|1 2|1 2|2 2 1 1 b 2 1 0 1 0 0
  • What is pivot?
  • How do I pivot?
  • Long format to wide format?

I've seen a lot of questions that ask about pivot tables, even if they don't know it. It is virtually impossible to write a canonical question and answer that encompasses all aspects of pivoting... But I'm going to give it a go.


The problem with existing questions and answers is that often the question is focused on a nuance that the OP has trouble generalizing in order to use a number of the existing good answers. However, none of the answers attempt to give a comprehensive explanation (because it's a daunting task). Look at a few examples from my Google search:

  1. How to pivot a dataframe in Pandas? - Good question and answer. But the answer only answers the specific question with little explanation.
  2. pandas pivot table to data frame - OP is concerned with the output of the pivot, namely how the columns look. OP wanted it to look like R. This isn't very helpful for pandas users.
  3. pandas pivoting a dataframe, duplicate rows - Another decent question but the answer focuses on one method, namely pd.DataFrame.pivot

Setup

I conspicuously named my columns and relevant column values to correspond with how I'm going to pivot in the answers below.

import numpy as np
import pandas as pd
from numpy.core.defchararray import add

np.random.seed([3,1415])
n = 20

cols = np.array(['key', 'row', 'item', 'col'])
arr1 = (np.random.randint(5, size=(n, 4)) // [2, 1, 2, 1]).astype(str)

df = pd.DataFrame(
    add(cols, arr1), columns=cols
).join(
    pd.DataFrame(np.random.rand(n, 2).round(2)).add_prefix('val')
)
print(df)
     key   row   item   col  val0  val1
0   key0  row3  item1  col3  0.81  0.04
1   key1  row2  item1  col2  0.44  0.07
2   key1  row0  item1  col0  0.77  0.01
3   key0  row4  item0  col2  0.15  0.59
4   key1  row0  item2  col1  0.81  0.64
5   key1  row2  item2  col4  0.13  0.88
6   key2  row4  item1  col3  0.88  0.39
7   key1  row4  item1  col1  0.10  0.07
8   key1  row0  item2  col4  0.65  0.02
9   key1  row2  item0  col2  0.35  0.61
10  key2  row0  item2  col1  0.40  0.85
11  key2  row4  item1  col2  0.64  0.25
12  key0  row2  item2  col3  0.50  0.44
13  key0  row4  item1  col4  0.24  0.46
14  key1  row3  item2  col3  0.28  0.11
15  key0  row3  item1  col1  0.31  0.23
16  key0  row0  item2  col3  0.86  0.01
17  key0  row4  item0  col3  0.64  0.21
18  key2  row2  item2  col0  0.13  0.45
19  key0  row2  item0  col4  0.37  0.70

Questions

  1. Why do I get ValueError: Index contains duplicate entries, cannot reshape?

  2. How do I pivot df such that the col values are columns, row values are the index, and mean of val0 are the values?

    col   col0   col1   col2   col3  col4
    row
    row0  0.77  0.605    NaN  0.860  0.65
    row2  0.13    NaN  0.395  0.500  0.25
    row3   NaN  0.310    NaN  0.545   NaN
    row4   NaN  0.100  0.395  0.760  0.24
    
  3. How do I make it so that missing values are 0?

    col   col0   col1   col2   col3  col4
    row
    row0  0.77  0.605  0.000  0.860  0.65
    row2  0.13  0.000  0.395  0.500  0.25
    row3  0.00  0.310  0.000  0.545  0.00
    row4  0.00  0.100  0.395  0.760  0.24
    
  4. Can I get something other than mean, like maybe sum?

    col   col0  col1  col2  col3  col4
    row
    row0  0.77  1.21  0.00  0.86  0.65
    row2  0.13  0.00  0.79  0.50  0.50
    row3  0.00  0.31  0.00  1.09  0.00
    row4  0.00  0.10  0.79  1.52  0.24
    
  5. Can I do more that one aggregation at a time?

           sum                          mean
    col   col0  col1  col2  col3  col4  col0   col1   col2   col3  col4
    row
    row0  0.77  1.21  0.00  0.86  0.65  0.77  0.605  0.000  0.860  0.65
    row2  0.13  0.00  0.79  0.50  0.50  0.13  0.000  0.395  0.500  0.25
    row3  0.00  0.31  0.00  1.09  0.00  0.00  0.310  0.000  0.545  0.00
    row4  0.00  0.10  0.79  1.52  0.24  0.00  0.100  0.395  0.760  0.24
    
  6. Can I aggregate over multiple value columns?

          val0                             val1
    col   col0   col1   col2   col3  col4  col0   col1  col2   col3  col4
    row
    row0  0.77  0.605  0.000  0.860  0.65  0.01  0.745  0.00  0.010  0.02
    row2  0.13  0.000  0.395  0.500  0.25  0.45  0.000  0.34  0.440  0.79
    row3  0.00  0.310  0.000  0.545  0.00  0.00  0.230  0.00  0.075  0.00
    row4  0.00  0.100  0.395  0.760  0.24  0.00  0.070  0.42  0.300  0.46
    
  7. Can I subdivide by multiple columns?

    item item0             item1                         item2
    col   col2  col3  col4  col0  col1  col2  col3  col4  col0   col1  col3  col4
    row
    row0  0.00  0.00  0.00  0.77  0.00  0.00  0.00  0.00  0.00  0.605  0.86  0.65
    row2  0.35  0.00  0.37  0.00  0.00  0.44  0.00  0.00  0.13  0.000  0.50  0.13
    row3  0.00  0.00  0.00  0.00  0.31  0.00  0.81  0.00  0.00  0.000  0.28  0.00
    row4  0.15  0.64  0.00  0.00  0.10  0.64  0.88  0.24  0.00  0.000  0.00  0.00
    
  8. Or

    item      item0             item1                         item2
    col        col2  col3  col4  col0  col1  col2  col3  col4  col0  col1  col3  col4
    key  row
    key0 row0  0.00  0.00  0.00  0.00  0.00  0.00  0.00  0.00  0.00  0.00  0.86  0.00
         row2  0.00  0.00  0.37  0.00  0.00  0.00  0.00  0.00  0.00  0.00  0.50  0.00
         row3  0.00  0.00  0.00  0.00  0.31  0.00  0.81  0.00  0.00  0.00  0.00  0.00
         row4  0.15  0.64  0.00  0.00  0.00  0.00  0.00  0.24  0.00  0.00  0.00  0.00
    key1 row0  0.00  0.00  0.00  0.77  0.00  0.00  0.00  0.00  0.00  0.81  0.00  0.65
         row2  0.35  0.00  0.00  0.00  0.00  0.44  0.00  0.00  0.00  0.00  0.00  0.13
         row3  0.00  0.00  0.00  0.00  0.00  0.00  0.00  0.00  0.00  0.00  0.28  0.00
         row4  0.00  0.00  0.00  0.00  0.10  0.00  0.00  0.00  0.00  0.00  0.00  0.00
    key2 row0  0.00  0.00  0.00  0.00  0.00  0.00  0.00  0.00  0.00  0.40  0.00  0.00
         row2  0.00  0.00  0.00  0.00  0.00  0.00  0.00  0.00  0.13  0.00  0.00  0.00
         row4  0.00  0.00  0.00  0.00  0.00  0.64  0.88  0.00  0.00  0.00  0.00  0.00
    
  9. Can I aggregate the frequency in which the column and rows occur together, aka "cross tabulation"?

    col   col0  col1  col2  col3  col4
    row
    row0     1     2     0     1     1
    row2     1     0     2     1     2
    row3     0     1     0     2     0
    row4     0     1     2     2     1
    
  10. How do I convert a DataFrame from long to wide by pivoting on ONLY two columns? Given,

    np.random.seed([3, 1415])
    df2 = pd.DataFrame({'A': list('aaaabbbc'), 'B': np.random.choice(15, 8)})
    df2
       A   B
    0  a   0
    1  a  11
    2  a   2
    3  a  11
    4  b  10
    5  b  10
    6  b  14
    7  c   7
    

    The expected should look something like

          a     b    c
    0   0.0  10.0  7.0
    1  11.0  10.0  NaN
    2   2.0  14.0  NaN
    3  11.0   NaN  NaN
    
  11. How do I flatten the multiple index to single index after pivot?

    From

       1  2
       1  1  2
    a  2  1  1
    b  2  1  0
    c  1  0  0
    

    To

       1|1  2|1  2|2
    a    2    1    1
    b    2    1    0
    c    1    0    0
    

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

此刻的回忆 2025-01-22 13:18:44

以下是我们可以用来进行透视的惯用法列表

  1. pd.DataFrame.pivot_table

    • groupby 的美化版本,具有更直观的 API。对于许多人来说,这是首选方法。这也是开发人员的预期方法。
    • 指定行级别、列级别、要聚合的值以及执行聚合的函数。
  2. pd.DataFrame.groupby+ pd.DataFrame.unstack

    • 适用于任何类型的数据透视的良好通用方法
    • 您指定将在一个分组依据中构成透视行级别和列级别的所有列。接下来,您可以选择要聚合的其余列以及要执行聚合的函数。最后,unstack您想要在列索引中出现的级别。

  3. pd.DataFrame.set_index+ pd.DataFrame.unstack

    • 对于某些人(包括我自己)来说方便且直观。无法处理重复的分组键。
    • groupby范例类似,我们指定最终将成为行或列级别的所有列,并将它们设置为索引。然后,我们在列中unstack我们想要的级别。如果剩余的索引级别或列级别不唯一,则此方法将失败。

  4. pd.DataFrame.pivot

    • set_index 非常相似,因为它具有重复键限制。 API 也非常有限。它只接受索引的标量值。
    • pivot_table 方法类似,我们选择要进行透视的行、列和值。但是,我们无法聚合,如果行或列不唯一,则此方法将失败。

  5. pd.crosstab

    • 这是 pivot_table 的专门版本,其最纯粹的形式是执行多项任务的最直观方式。

  6. pd.factorize + np.bincount

    • 这是一种非常先进的技术,虽然非常晦涩,但速度非常快。它不可能在所有情况下都使用,但是当它可以使用并且您可以轻松使用它时,您将获得性能奖励。
  7. pd.get_dummies + pd.DataFrame.dot

    • 我用它来巧妙地执行交叉制表。

另请参阅:


问题 1

为什么我会收到ValueError:索引包含重复条目,无法重塑

发生这种情况是因为 pandas 试图对具有重复项的 columnsindex 对象重新建立索引条目。有多种方法可以用来执行枢转。其中一些不太适合当要求旋转的键重复时。例如:考虑pd.DataFrame.pivot。我知道有重复的条目共享 rowcol 值:

df.duplicated(['row', 'col']).any()

True

因此,当我使用 pivot 时,

df.pivot(index='row', columns='col', values='val0')

我收到上述错误。事实上,当我尝试执行相同的任务时,我遇到了同样的错误:

df.set_index(['row', 'col'])['val0'].unstack()

示例

对于每个后续问题,我要做的是使用 pd.DataFrame.pivot_table。然后我将提供执行相同任务的替代方案。

问题2和3

如何对 df 进行透视,使 col 值是列,row 值是索引,以及 val0 的平均值 是值吗?

  • pd.DataFrame.pivot_table

    df.pivot_table(
        值='val0',索引='行',列='列',
        aggfunc='意思')
    
    科尔 科尔0 科尔1 科尔2 科尔3 科尔4
    排                                  
    行 0 0.77 0.605 南 0.860 0.65
    第 2 行 0.13 南 0.395 0.500 0.25
    第 3 行 南 0.310 南 0.545 南
    第 4 行 南 0.100 0.395 0.760 0.24
    
    • aggfunc='mean' 是默认值,我不必设置它。我将其包含在内是为了明确。

如何使缺失值为 0?

  • pd.DataFrame.pivot_table

      默认情况下不设置

    • fill_value。我倾向于适当地设置它。在本例中,我将其设置为 0
    df.pivot_table(
        值='val0',索引='行',列='列',
        fill_value=0, aggfunc='mean')
    
    科尔 科尔0 科尔1 科尔2 科尔3 科尔4
    排
    第 0 行 0.77 0.605 0.000 0.860 0.65
    第2行 0.13 0.000 0.395 0.500 0.25
    第3行 0.00 0.310 0.000 0.545 0.00
    第4行 0.00 0.100 0.395 0.760 0.24
    
  • pd.DataFrame.groupby

    df.groupby(['row', 'col'])['val0'].mean().unstack(fill_value=0)
    

  • pd.crosstab

    <前><代码>pd.crosstab(
    索引=df['行'], 列=df['列'],
    值=df['val0'], aggfunc='mean').fillna(0)


问题4

我可以得到除mean以外的东西,比如sum吗?

  • pd.DataFrame.pivot_table

    df.pivot_table(
        值='val0',索引='行',列='列',
        fill_value=0, aggfunc='sum')
    
    科尔 科尔0 科尔1 科尔2 科尔3 科尔4
    排
    第 0 行 0.77 1.21 0.00 0.86 0.65
    第2行 0.13 0.00 0.79 0.50 0.50
    第三行 0.00 0.31 0.00 1.09 0.00
    第4行 0.00 0.10 0.79 1.52 0.24
    
  • pd.DataFrame.groupby

    df.groupby(['row', 'col'])['val0'].sum().unstack(fill_value=0)
    
  • pd.crosstab

    <前><代码>pd.crosstab(
    索引=df['行'], 列=df['列'],
    值=df['val0'], aggfunc='sum').fillna(0)


问题5

我可以一次进行多个聚合吗?

请注意,对于 pivot_tablecrosstab 我需要传递可调用列表。另一方面,groupby.agg 能够为有限数量的特殊函数获取字符串。 groupby.agg 也会采用我们传递给其他函数的相同可调用函数,但利用字符串函数名称通常会更有效,因为可以提高效率。

  • pd.DataFrame.pivot_table

    df.pivot_table(
        值='val0',索引='行',列='列',
        fill_value=0, aggfunc=[np.size, np.mean])
    
         尺寸平均值
    科尔 科尔0 科尔1 科尔2 科尔3 科尔4 科尔0 科尔1 科尔2 科尔3 科尔4
    排
    行0 1 2 0 1 1 0.77 0.605 0.000 0.860 0.65
    第2行 1 0 2 1 2 0.13 0.000 0.395 0.500 0.25
    第3行 0 1 0 2 0 0.00 0.310 0.000 0.545 0.00
    第4行 0 1 2 2 1 0.00 0.100 0.395 0.760 0.24
    
  • pd.DataFrame.groupby

    df.groupby(['row', 'col'])['val0'].agg(['size', 'mean']).unstack(fill_value=0)
    
  • pd.crosstab

    <前><代码>pd.crosstab(
    索引=df['行'], 列=df['列'],
    值=df['val0'], aggfunc=[np.size, np.mean]).fillna(0, downcast='infer')


问题6

我可以聚合多个值列吗?

  • pd.DataFrame.pivot_table我们传递了values=['val0', 'val1'],但我们可以完全放弃它

    df.pivot_table(
        值=['val0','val1'],索引='行',列='列',
        fill_value=0, aggfunc='mean')
    
          值0 值1
    科尔 科尔0 科尔1 科尔2 科尔3 科尔4 科尔0 科尔1 科尔2 科尔3 科尔4
    排
    行0 0.77 0.605 0.000 0.860 0.65 0.01 0.745 0.00 0.010 0.02
    第2行 0.13 0.000 0.395 0.500 0.25 0.45 0.000 0.34 0.440 0.79
    第三行 0.00 0.310 0.000 0.545 0.00 0.00 0.230 0.00 0.075 0.00
    第4行 0.00 0.100 0.395 0.760 0.24 0.00 0.070 0.42 0.300 0.46
    
  • pd.DataFrame.groupby

    df.groupby(['row', 'col'])['val0', 'val1'].mean().unstack(fill_value=0)
    

问题7

我可以细分多列吗?

  • pd.DataFrame.pivot_table

    df.pivot_table(
        值='val0',索引='行',列=['项目','列'],
        fill_value=0, aggfunc='mean')
    
    项目 项目0 项目1 项目2
    科尔 科尔2 科尔3 科尔4 科尔0 科尔1 科尔2 科尔3 科尔4 科尔0 科尔1 科尔3 科尔4
    排
    行0 0.00 0.00 0.00 0.77 0.00 0.00 0.00 0.00 0.00 0.605 0.86 0.65
    第2行 0.35 0.00 0.37 0.00 0.00 0.44 0.00 0.00 0.13 0.000 0.50 0.13
    第三行 0.00 0.00 0.00 0.00 0.31 0.00 0.81 0.00 0.00 0.000 0.28 0.00
    第4行 0.15 0.64 0.00 0.00 0.10 0.64 0.88 0.24 0.00 0.000 0.00 0.00
    
  • pd.DataFrame.groupby

    df.groupby(
        ['行'、'项目'、'列']
    )['val0'].mean().unstack(['item', 'col']).fillna(0).sort_index(1)
    

问题8

我可以细分多列吗?

  • pd.DataFrame.pivot_table

    df.pivot_table(
        值='val0',索引=['键','行'],列=['项目','列'],
        fill_value=0, aggfunc='mean')
    
    项目 项目0 项目1 项目2
    科尔 科尔2 科尔3 科尔4 科尔0 科尔1 科尔2 科尔3 科尔4 科尔0 科尔1 科尔3 科尔4
    关键行
    键0行0 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.86 0.00
         第2行 0.00 0.00 0.37 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.50 0.00
         第三行 0.00 0.00 0.00 0.00 0.31 0.00 0.81 0.00 0.00 0.00 0.00 0.00
         第4行 0.15 0.64 0.00 0.00 0.00 0.00 0.00 0.24 0.00 0.00 0.00 0.00
    键1行0 0.00 0.00 0.00 0.77 0.00 0.00 0.00 0.00 0.00 0.81 0.00 0.65
         第2行 0.35 0.00 0.00 0.00 0.00 0.44 0.00 0.00 0.00 0.00 0.00 0.13
         第三行 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.28 0.00
         第4行 0.00 0.00 0.00 0.00 0.10 0.00 0.00 0.00 0.00 0.00 0.00 0.00
    键2行0 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.40 0.00 0.00
         第2行 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.13 0.00 0.00 0.00
         第4行 0.00 0.00 0.00 0.00 0.00 0.64 0.88 0.00 0.00 0.00 0.00 0.00
    
  • pd.DataFrame.groupby

    df.groupby(
        ['键'、'行'、'项目'、'列']
    )['val0'].mean().unstack(['item', 'col']).fillna(0).sort_index(1)
    
  • pd.DataFrame.set_index 因为该组键对于行和列都是唯一的

    df.set_index(
        ['键'、'行'、'项目'、'列']
    )['val0'].unstack(['item', 'col']).fillna(0).sort_index(1)
    

问题 9

我可以聚合列和行一起出现的频率,即“交叉制表”吗?

  • pd.DataFrame.pivot_table

    df.pivot_table(index='row', columns='col', fill_value=0, aggfunc='size')
    
    科尔 科尔0 科尔1 科尔2 科尔3 科尔4
    排
    行0 1 2 0 1 1
    第2行 1 0 2 1 2
    行3 0 1 0 2 0
    第4行0 1 2 2 1
    
  • pd.DataFrame.groupby

    df.groupby(['row', 'col'])['val0'].size().unstack(fill_value=0)
    
  • pd.crosstab

    pd.crosstab(df['row'], df['col'])
    
  • < p>pd.factorize + np.bincount

    # 获取整数分解 `i` 和唯一值 `r`
    # 对于列“行”
    i, r = pd.factorize(df['row'].values)
    # 获取整数分解`j`和唯一值`c`
    # 对于列 `'col'`
    j, c = pd.factorize(df['col'].values)
    # `n` 将是行数
    # `m` 将是列数
    n, m = r.尺寸, c.尺寸
    # `i * m + j` 是一种聪明的计算方法
    # 分解箱假设长度为平面数组
    # `n * m`。这就是为什么我们随后将其重塑为“(n, m)”
    b = np.bincount(i * m + j, minlength=n * m).reshape(n, m)
    # 顺便说一句,每当我读到这篇文章时,我都会想到“豆子、大米和奶酪”
    pd.DataFrame(b, r, c)
    
          col3 col2 col0 col1 col4
    行3 2 0 0 1 0
    第2行 1 2 1 0 2
    行0 1 0 1 2 1
    第4行 2 2 0 1 1
    
  • pd.get_dummies

    pd.get_dummies(df['row']).T.dot(pd.get_dummies(df['col']))
    
          列0 列1 列2 列3 列4
    行0 1 2 0 1 1
    第2行 1 0 2 1 2
    行3 0 1 0 2 0
    第4行0 1 2 2 1
    

问题10

如何通过仅旋转两个数据帧将长数据帧转换为宽数据帧
列?

  • DataFrame.pivot

    第一步是为每一行分配一个数字 - 该数字将是透视结果中该值的行索引。这是使用 完成的GroupBy.cumcount

    df2.insert(0, 'count', df2.groupby('A').cumcount())
    df2
    
       计数AB
    0 0 一个 0
    1 1 11
    2 2 2
    3 3 11
    4 0 b 10
    5 1 b 10
    6 2 b 14
    7 0 c 7
    

    第二步是使用新创建的列作为索引来调用 DataFrame.pivot

    df2.pivot(*df2)
    # df2.pivot(索引='计数',列='A',值='B')
    
    一个abc
    数数
    0 0.0 10.0 7.0
    1 11.0 10.0 南
    2 2.0 14.0 南
    3 11.0 南 南
    
  • DataFrame.pivot_table

    DataFrame.pivot 仅接受列,DataFrame.pivot_table 也接受数组,因此 GroupBy.cumcount 可以直接作为 index 传递无需创建显式列。

    df2.pivot_table(index=df2.groupby('A').cumcount(),columns='A',values='B')
    
    一个abc
    0 0.0 10.0 7.0
    1 11.0 10.0 南
    2 2.0 14.0 南
    3 11.0 南 南
    


问题11

如何在pivot之后将多个索引展平为单个索引

如果columns类型带有字符串joinobject

df.columns = df.columns.map('|'.join)

else 格式

df.columns = df.columns.map('{0[0]}|{0[1]}'.format)

Here is a list of idioms we can use to pivot

  1. pd.DataFrame.pivot_table

    • A glorified version of groupby with more intuitive API. For many people, this is the preferred approach. And it is the intended approach by the developers.
    • Specify row level, column levels, values to be aggregated, and function(s) to perform aggregations.
  2. pd.DataFrame.groupby + pd.DataFrame.unstack

    • Good general approach for doing just about any type of pivot
    • You specify all columns that will constitute the pivoted row levels and column levels in one group by. You follow that by selecting the remaining columns you want to aggregate and the function(s) you want to perform the aggregation. Finally, you unstack the levels that you want to be in the column index.
  3. pd.DataFrame.set_index + pd.DataFrame.unstack

    • Convenient and intuitive for some (myself included). Cannot handle duplicate grouped keys.
    • Similar to the groupby paradigm, we specify all columns that will eventually be either row or column levels and set those to be the index. We then unstack the levels we want in the columns. If either the remaining index levels or column levels are not unique, this method will fail.
  4. pd.DataFrame.pivot

    • Very similar to set_index in that it shares the duplicate key limitation. The API is very limited as well. It only takes scalar values for index, columns, values.
    • Similar to the pivot_table method in that we select rows, columns, and values on which to pivot. However, we cannot aggregate and if either rows or columns are not unique, this method will fail.
  5. pd.crosstab

    • This a specialized version of pivot_table and in its purest form is the most intuitive way to perform several tasks.
  6. pd.factorize + np.bincount

    • This is a highly advanced technique that is very obscure but is very fast. It cannot be used in all circumstances, but when it can be used and you are comfortable using it, you will reap the performance rewards.
  7. pd.get_dummies + pd.DataFrame.dot

    • I use this for cleverly performing cross tabulation.

See also:


Question 1

Why do I get ValueError: Index contains duplicate entries, cannot reshape

This occurs because pandas is attempting to reindex either a columns or index object with duplicate entries. There are varying methods to use that can perform a pivot. Some of them are not well suited to when there are duplicates of the keys on which it is being asked to pivot. For example: Consider pd.DataFrame.pivot. I know there are duplicate entries that share the row and col values:

df.duplicated(['row', 'col']).any()

True

So when I pivot using

df.pivot(index='row', columns='col', values='val0')

I get the error mentioned above. In fact, I get the same error when I try to perform the same task with:

df.set_index(['row', 'col'])['val0'].unstack()

Examples

What I'm going to do for each subsequent question is to answer it using pd.DataFrame.pivot_table. Then I'll provide alternatives to perform the same task.

Questions 2 and 3

How do I pivot df such that the col values are columns, row values are the index, and mean of val0 are the values?

  • pd.DataFrame.pivot_table

    df.pivot_table(
        values='val0', index='row', columns='col',
        aggfunc='mean')
    
    col   col0   col1   col2   col3  col4
    row                                  
    row0  0.77  0.605    NaN  0.860  0.65
    row2  0.13    NaN  0.395  0.500  0.25
    row3   NaN  0.310    NaN  0.545   NaN
    row4   NaN  0.100  0.395  0.760  0.24
    
    • aggfunc='mean' is the default and I didn't have to set it. I included it to be explicit.

How do I make it so that missing values are 0?

  • pd.DataFrame.pivot_table

    • fill_value is not set by default. I tend to set it appropriately. In this case I set it to 0.
    df.pivot_table(
        values='val0', index='row', columns='col',
        fill_value=0, aggfunc='mean')
    
    col   col0   col1   col2   col3  col4
    row
    row0  0.77  0.605  0.000  0.860  0.65
    row2  0.13  0.000  0.395  0.500  0.25
    row3  0.00  0.310  0.000  0.545  0.00
    row4  0.00  0.100  0.395  0.760  0.24
    
  • pd.DataFrame.groupby

    df.groupby(['row', 'col'])['val0'].mean().unstack(fill_value=0)
    
  • pd.crosstab

    pd.crosstab(
        index=df['row'], columns=df['col'],
        values=df['val0'], aggfunc='mean').fillna(0)
    

Question 4

Can I get something other than mean, like maybe sum?

  • pd.DataFrame.pivot_table

    df.pivot_table(
        values='val0', index='row', columns='col',
        fill_value=0, aggfunc='sum')
    
    col   col0  col1  col2  col3  col4
    row
    row0  0.77  1.21  0.00  0.86  0.65
    row2  0.13  0.00  0.79  0.50  0.50
    row3  0.00  0.31  0.00  1.09  0.00
    row4  0.00  0.10  0.79  1.52  0.24
    
  • pd.DataFrame.groupby

    df.groupby(['row', 'col'])['val0'].sum().unstack(fill_value=0)
    
  • pd.crosstab

    pd.crosstab(
        index=df['row'], columns=df['col'],
        values=df['val0'], aggfunc='sum').fillna(0)
    

Question 5

Can I do more that one aggregation at a time?

Notice that for pivot_table and crosstab I needed to pass list of callables. On the other hand, groupby.agg is able to take strings for a limited number of special functions. groupby.agg would also have taken the same callables we passed to the others, but it is often more efficient to leverage the string function names as there are efficiencies to be gained.

  • pd.DataFrame.pivot_table

    df.pivot_table(
        values='val0', index='row', columns='col',
        fill_value=0, aggfunc=[np.size, np.mean])
    
         size                      mean
    col  col0 col1 col2 col3 col4  col0   col1   col2   col3  col4
    row
    row0    1    2    0    1    1  0.77  0.605  0.000  0.860  0.65
    row2    1    0    2    1    2  0.13  0.000  0.395  0.500  0.25
    row3    0    1    0    2    0  0.00  0.310  0.000  0.545  0.00
    row4    0    1    2    2    1  0.00  0.100  0.395  0.760  0.24
    
  • pd.DataFrame.groupby

    df.groupby(['row', 'col'])['val0'].agg(['size', 'mean']).unstack(fill_value=0)
    
  • pd.crosstab

    pd.crosstab(
        index=df['row'], columns=df['col'],
        values=df['val0'], aggfunc=[np.size, np.mean]).fillna(0, downcast='infer')
    

Question 6

Can I aggregate over multiple value columns?

  • pd.DataFrame.pivot_table we pass values=['val0', 'val1'] but we could've left that off completely

    df.pivot_table(
        values=['val0', 'val1'], index='row', columns='col',
        fill_value=0, aggfunc='mean')
    
          val0                             val1
    col   col0   col1   col2   col3  col4  col0   col1  col2   col3  col4
    row
    row0  0.77  0.605  0.000  0.860  0.65  0.01  0.745  0.00  0.010  0.02
    row2  0.13  0.000  0.395  0.500  0.25  0.45  0.000  0.34  0.440  0.79
    row3  0.00  0.310  0.000  0.545  0.00  0.00  0.230  0.00  0.075  0.00
    row4  0.00  0.100  0.395  0.760  0.24  0.00  0.070  0.42  0.300  0.46
    
  • pd.DataFrame.groupby

    df.groupby(['row', 'col'])['val0', 'val1'].mean().unstack(fill_value=0)
    

Question 7

Can I subdivide by multiple columns?

  • pd.DataFrame.pivot_table

    df.pivot_table(
        values='val0', index='row', columns=['item', 'col'],
        fill_value=0, aggfunc='mean')
    
    item item0             item1                         item2
    col   col2  col3  col4  col0  col1  col2  col3  col4  col0   col1  col3  col4
    row
    row0  0.00  0.00  0.00  0.77  0.00  0.00  0.00  0.00  0.00  0.605  0.86  0.65
    row2  0.35  0.00  0.37  0.00  0.00  0.44  0.00  0.00  0.13  0.000  0.50  0.13
    row3  0.00  0.00  0.00  0.00  0.31  0.00  0.81  0.00  0.00  0.000  0.28  0.00
    row4  0.15  0.64  0.00  0.00  0.10  0.64  0.88  0.24  0.00  0.000  0.00  0.00
    
  • pd.DataFrame.groupby

    df.groupby(
        ['row', 'item', 'col']
    )['val0'].mean().unstack(['item', 'col']).fillna(0).sort_index(1)
    

Question 8

Can I subdivide by multiple columns?

  • pd.DataFrame.pivot_table

    df.pivot_table(
        values='val0', index=['key', 'row'], columns=['item', 'col'],
        fill_value=0, aggfunc='mean')
    
    item      item0             item1                         item2
    col        col2  col3  col4  col0  col1  col2  col3  col4  col0  col1  col3  col4
    key  row
    key0 row0  0.00  0.00  0.00  0.00  0.00  0.00  0.00  0.00  0.00  0.00  0.86  0.00
         row2  0.00  0.00  0.37  0.00  0.00  0.00  0.00  0.00  0.00  0.00  0.50  0.00
         row3  0.00  0.00  0.00  0.00  0.31  0.00  0.81  0.00  0.00  0.00  0.00  0.00
         row4  0.15  0.64  0.00  0.00  0.00  0.00  0.00  0.24  0.00  0.00  0.00  0.00
    key1 row0  0.00  0.00  0.00  0.77  0.00  0.00  0.00  0.00  0.00  0.81  0.00  0.65
         row2  0.35  0.00  0.00  0.00  0.00  0.44  0.00  0.00  0.00  0.00  0.00  0.13
         row3  0.00  0.00  0.00  0.00  0.00  0.00  0.00  0.00  0.00  0.00  0.28  0.00
         row4  0.00  0.00  0.00  0.00  0.10  0.00  0.00  0.00  0.00  0.00  0.00  0.00
    key2 row0  0.00  0.00  0.00  0.00  0.00  0.00  0.00  0.00  0.00  0.40  0.00  0.00
         row2  0.00  0.00  0.00  0.00  0.00  0.00  0.00  0.00  0.13  0.00  0.00  0.00
         row4  0.00  0.00  0.00  0.00  0.00  0.64  0.88  0.00  0.00  0.00  0.00  0.00
    
  • pd.DataFrame.groupby

    df.groupby(
        ['key', 'row', 'item', 'col']
    )['val0'].mean().unstack(['item', 'col']).fillna(0).sort_index(1)
    
  • pd.DataFrame.set_index because the set of keys are unique for both rows and columns

    df.set_index(
        ['key', 'row', 'item', 'col']
    )['val0'].unstack(['item', 'col']).fillna(0).sort_index(1)
    

Question 9

Can I aggregate the frequency in which the column and rows occur together, aka "cross tabulation"?

  • pd.DataFrame.pivot_table

    df.pivot_table(index='row', columns='col', fill_value=0, aggfunc='size')
    
    col   col0  col1  col2  col3  col4
    row
    row0     1     2     0     1     1
    row2     1     0     2     1     2
    row3     0     1     0     2     0
    row4     0     1     2     2     1
    
  • pd.DataFrame.groupby

    df.groupby(['row', 'col'])['val0'].size().unstack(fill_value=0)
    
  • pd.crosstab

    pd.crosstab(df['row'], df['col'])
    
  • pd.factorize + np.bincount

    # get integer factorization `i` and unique values `r`
    # for column `'row'`
    i, r = pd.factorize(df['row'].values)
    # get integer factorization `j` and unique values `c`
    # for column `'col'`
    j, c = pd.factorize(df['col'].values)
    # `n` will be the number of rows
    # `m` will be the number of columns
    n, m = r.size, c.size
    # `i * m + j` is a clever way of counting the
    # factorization bins assuming a flat array of length
    # `n * m`.  Which is why we subsequently reshape as `(n, m)`
    b = np.bincount(i * m + j, minlength=n * m).reshape(n, m)
    # BTW, whenever I read this, I think 'Bean, Rice, and Cheese'
    pd.DataFrame(b, r, c)
    
          col3  col2  col0  col1  col4
    row3     2     0     0     1     0
    row2     1     2     1     0     2
    row0     1     0     1     2     1
    row4     2     2     0     1     1
    
  • pd.get_dummies

    pd.get_dummies(df['row']).T.dot(pd.get_dummies(df['col']))
    
          col0  col1  col2  col3  col4
    row0     1     2     0     1     1
    row2     1     0     2     1     2
    row3     0     1     0     2     0
    row4     0     1     2     2     1
    

Question 10

How do I convert a DataFrame from long to wide by pivoting on ONLY two
columns?

  • DataFrame.pivot

    The first step is to assign a number to each row - this number will be the row index of that value in the pivoted result. This is done using GroupBy.cumcount:

    df2.insert(0, 'count', df2.groupby('A').cumcount())
    df2
    
       count  A   B
    0      0  a   0
    1      1  a  11
    2      2  a   2
    3      3  a  11
    4      0  b  10
    5      1  b  10
    6      2  b  14
    7      0  c   7
    

    The second step is to use the newly created column as the index to call DataFrame.pivot.

    df2.pivot(*df2)
    # df2.pivot(index='count', columns='A', values='B')
    
    A         a     b    c
    count
    0       0.0  10.0  7.0
    1      11.0  10.0  NaN
    2       2.0  14.0  NaN
    3      11.0   NaN  NaN
    
  • DataFrame.pivot_table

    Whereas DataFrame.pivot only accepts columns, DataFrame.pivot_table also accepts arrays, so the GroupBy.cumcount can be passed directly as the index without creating an explicit column.

    df2.pivot_table(index=df2.groupby('A').cumcount(), columns='A', values='B')
    
    A         a     b    c
    0       0.0  10.0  7.0
    1      11.0  10.0  NaN
    2       2.0  14.0  NaN
    3      11.0   NaN  NaN
    

Question 11

How do I flatten the multiple index to single index after pivot

If columns type object with string join

df.columns = df.columns.map('|'.join)

else format

df.columns = df.columns.map('{0[0]}|{0[1]}'.format)
柏拉图鍀咏恒 2025-01-22 13:18:44

@piRSquared的答案扩展为问题 10

问题 10.1

DataFrame:

d = data = {'A': {0: 1, 1: 1, 2: 1, 3: 2, 4: 2, 5: 3, 6: 5},
 'B': {0: 'a', 1: 'b', 2: 'c', 3: 'a', 4: 'b', 5: 'a', 6: 'c'}}
df = pd.DataFrame(d)

   A  B
0  1  a
1  1  b
2  1  c
3  2  a
4  2  b
5  3  a
6  5  c

输出:

   0     1     2
A
1  a     b     c
2  a     b  None
3  a  None  None
5  c  None  None

使用 df .groupby<代码>pd.Series.tolist

t = df.groupby('A')['B'].apply(list)
out = pd.DataFrame(t.tolist(),index=t.index)
out
   0     1     2
A
1  a     b     c
2  a     b  None
3  a  None  None
5  c  None  None

或者
使用 pd.pivot_tabledf.squeeze。

t = df.pivot_table(index='A',values='B',aggfunc=list).squeeze()
out = pd.DataFrame(t.tolist(),index=t.index)

To extend @piRSquared's answer another version of Question 10

Question 10.1

DataFrame:

d = data = {'A': {0: 1, 1: 1, 2: 1, 3: 2, 4: 2, 5: 3, 6: 5},
 'B': {0: 'a', 1: 'b', 2: 'c', 3: 'a', 4: 'b', 5: 'a', 6: 'c'}}
df = pd.DataFrame(d)

   A  B
0  1  a
1  1  b
2  1  c
3  2  a
4  2  b
5  3  a
6  5  c

Output:

   0     1     2
A
1  a     b     c
2  a     b  None
3  a  None  None
5  c  None  None

Using df.groupby and pd.Series.tolist

t = df.groupby('A')['B'].apply(list)
out = pd.DataFrame(t.tolist(),index=t.index)
out
   0     1     2
A
1  a     b     c
2  a     b  None
3  a  None  None
5  c  None  None

Or
A much better alternative using pd.pivot_table with df.squeeze.

t = df.pivot_table(index='A',values='B',aggfunc=list).squeeze()
out = pd.DataFrame(t.tolist(),index=t.index)
梦途 2025-01-22 13:18:44

为了更好地理解函数 pivot 的工作原理你可以看看 示例。但是,如果您有重复的索引列 (foo-bar) 组合(如中的 df),pivot 将会失败第二个示例):

pivot

pivot 相反,函数 pivot_table 支持使用 mean 函数。以下是 sum 聚合函数的示例:

pivot_table

To better understand how the function pivot works you can look at the example from Pandas documentation. However pivot will fail if you have repeating index-columns (foo-bar) combinations (like df in the second example):

pivot

In opposite to pivot the function pivot_table supports data aggregation using the mean function by default. Here is an example with the sum aggregation function:

pivot_table

月下客 2025-01-22 13:18:44

调用 reset_index()(连同 add_suffix()

通常,在调用 pivot_table 后需要 reset_index()枢轴。例如,要进行以下转换(其中一列成为列名称)

< img src="https://i.sstatic.net/SlCqF.png" alt="res">

您使用以下代码,在 pivot 之后,您将前缀添加到新创建的列名称和将索引(在本例中为“movies”)转换回列并删除轴名称的名称:

df.pivot(index='movie', columns='week', values='sales').add_prefix('week_').reset_index().rename_axis(columns=None)

正如其他答案提到的,“pivot”可能指的是 2 个不同的操作:

  1. Unstacked 聚合(即使 groupby.agg 的结果更宽。)
  2. 重塑(类似于 Excel 中的透视、numpy 中的reshape 或 R 中的pivot_wider

1.聚合

pivot_tablecrosstab 只是 groupby.agg 操作的未堆叠结果。事实上,源代码表明,在幕后,以下内容是正确的:

  • pivot_table = groupby + unstack (阅读此处了解更多信息。)
  • crosstab = pivot_table

注意您可以使用作为 indexcolumnsvalues 参数的列名称列表。

df.groupby(rows+cols)[vals].agg(aggfuncs).unstack(cols)
# equivalently,
df.pivot_table(vals, rows, cols, aggfuncs)
1.1. crosstabpivot_table 的特例;因此 groupby + unstack

以下是等效的:

  • pd.crosstab(df['colA'], df['colB'])
  • <代码>df.pivot_table(index='colA', columns='colB', aggfunc='size', fill_value=0)
  • df.groupby(['colA', 'colB']).size().unstack(fill_value=0)

请注意,pd.crosstab 的开销明显更大,因此它比 pivot_table 慢得多代码> 和<代码>groupby + <代码>unstack。事实上,正如此处指出的pivot_tablegroupby慢+ unstack 也是如此。

2. 重塑

pivotpivot_table的一个更有限的版本,其目的是将长数据帧重塑为长数据帧。

df.set_index(rows+cols)[vals].unstack(cols)
# equivalently, 
df.pivot(index=rows, columns=cols, values=vals)
2.1.如问题 10 中那样增加行/列

您还可以将问题 10 中的见解应用到多列透视操作。有两种情况:

  • “long-to-long”:通过增加索引来重塑

    “案例1”

    代码:

    df = pd.DataFrame({'A': [1, 1, 1, 2, 2, 2], 'B': [*'xxyyzz' ], 
                       'C': [*'CCDCDD'], 'E': [100, 200, 300, 400, 500, 600]})
    行、列、值 = ['A', 'B'], ['C'], 'E'
    
    # 使用透视语法
    df1 = (
        df.assign(ix=df.groupby(行+列).cumcount())
        .pivot(索引=[*行,'ix'],列=列,值=值)
        .fillna(0, 向下转型='推断')
        .droplevel(-1).reset_index().rename_axis(columns=None)
    )
    
    # 等效地,使用 set_index + unstack 语法
    df1 = (
        df
        .set_index([*rows, df.groupby(rows+cols).cumcount(), *cols])[vals]
        .unstack(fill_value=0)
        .droplevel(-1).reset_index().rename_axis(columns=None)
    )
    
  • “长到宽”:通过增加列来重塑

    “案例2”

    代码:

    df1 = (
        df.assign(ix=df.groupby(行+列).cumcount())
        .pivot(索引=行,列=[*列,'ix'])[vals]
        .fillna(0, 向下转型='推断')
    )
    df1 = df1.set_axis([f"{c[0]}_{c[1]}" for c in df1], axis=1).reset_index()
    
    # 等效地,使用 set_index + unstack 语法
    df1 = (
        df
        .set_index([*rows, df.groupby(rows+cols).cumcount(), *cols])[vals]
        .unstack([-1, *范围(-2, -len(列)-2, -1)], fill_value=0)
    )
    df1 = df1.set_axis([f"{c[0]}_{c[1]}" for c in df1], axis=1).reset_index()
    
  • 使用 set_index + unstack语法:

    “案例3”

    代码:

    df1 = df.set_index(['A', df.groupby('A').cumcount()])['E'].unstack(fill_value =0).add_prefix('Col').reset_index()
    

1 pivot_table() 聚合价值观和将其拆开。具体来说,它从索引和列中创建一个平面列表,使用该列表作为分组调用 groupby() ,并使用传递的聚合器方法进行聚合(默认为 mean )。然后在聚合之后,它通过列列表调用unstack()。所以在内部,pivot_table = groupby + unstack。此外,如果传递了 fill_value,则会调用 fillna()

换句话说,生成 pv_1 的方法与下面示例中生成 gb_1 的方法相同。

pv_1 = df.pivot_table(index=rows, columns=cols, values=vals, aggfunc=aggfuncs, fill_value=0)
# internal operation of `pivot_table()`
gb_1 = df.groupby(rows+cols)[vals].agg(aggfuncs).unstack(cols).fillna(0, downcast="infer")
pv_1.equals(gb_1) # True

2 crosstab() 调用pivot_table(),即crosstab =ivot_table。具体来说,它根据传递的值数组构建一个 DataFrame,通过公共索引对其进行过滤并调用pivot_table()。它比 pivot_table() 受到更多限制,因为它只允许使用类似一维数组的 values,这与可以有多个值的 pivot_table() 不同。列作为

Call reset_index() (along with add_suffix())

Oftentimes, reset_index() is needed after you call pivot_table or pivot. For example, to make the following transformation (where one column become column names)

res

you use the following code, where after pivot, you add prefix to the newly created column names and convert the index (in this case "movies") back into a column and remove the name of the axis name:

df.pivot(index='movie', columns='week', values='sales').add_prefix('week_').reset_index().rename_axis(columns=None)

As the other answers mentioned, "pivot" may refer to 2 different operations:

  1. Unstacked aggregation (i.e. make the results of groupby.agg wider.)
  2. Reshaping (similar to pivot in Excel, reshape in numpy or pivot_wider in R)

1. Aggregation

pivot_table or crosstab are simply unstacked results of groupby.agg operation. In fact, the source code shows that, under the hood, the following are true:

  • pivot_table = groupby + unstack (read here for more info.)
  • crosstab = pivot_table

N.B. You can use list of column names as index, columns and values arguments.

df.groupby(rows+cols)[vals].agg(aggfuncs).unstack(cols)
# equivalently,
df.pivot_table(vals, rows, cols, aggfuncs)
1.1. crosstab is a special case of pivot_table; thus of groupby + unstack

The following are equivalent:

  • pd.crosstab(df['colA'], df['colB'])
  • df.pivot_table(index='colA', columns='colB', aggfunc='size', fill_value=0)
  • df.groupby(['colA', 'colB']).size().unstack(fill_value=0)

Note that pd.crosstab has a significantly larger overhead, so it's significantly slower than both pivot_table and groupby + unstack. In fact, as noted here, pivot_table is slower than groupby + unstack as well.

2. Reshaping

pivot is a more limited version of pivot_table where its purpose is to reshape a long dataframe into a long one.

df.set_index(rows+cols)[vals].unstack(cols)
# equivalently, 
df.pivot(index=rows, columns=cols, values=vals)
2.1. Augment rows/columns as in Question 10

You can also apply the insight from Question 10 to multi-column pivot operation as well. There are two cases:

  • "long-to-long": reshape by augmenting the indices

    case1

    Code:

    df = pd.DataFrame({'A': [1, 1, 1, 2, 2, 2], 'B': [*'xxyyzz'], 
                       'C': [*'CCDCDD'], 'E': [100, 200, 300, 400, 500, 600]})
    rows, cols, vals = ['A', 'B'], ['C'], 'E'
    
    # using pivot syntax
    df1 = (
        df.assign(ix=df.groupby(rows+cols).cumcount())
        .pivot(index=[*rows, 'ix'], columns=cols, values=vals)
        .fillna(0, downcast='infer')
        .droplevel(-1).reset_index().rename_axis(columns=None)
    )
    
    # equivalently, using set_index + unstack syntax
    df1 = (
        df
        .set_index([*rows, df.groupby(rows+cols).cumcount(), *cols])[vals]
        .unstack(fill_value=0)
        .droplevel(-1).reset_index().rename_axis(columns=None)
    )
    
  • "long-to-wide": reshape by augmenting the columns

    case2

    Code:

    df1 = (
        df.assign(ix=df.groupby(rows+cols).cumcount())
        .pivot(index=rows, columns=[*cols, 'ix'])[vals]
        .fillna(0, downcast='infer')
    )
    df1 = df1.set_axis([f"{c[0]}_{c[1]}" for c in df1], axis=1).reset_index()
    
    # equivalently, using the set_index + unstack syntax
    df1 = (
        df
        .set_index([*rows, df.groupby(rows+cols).cumcount(), *cols])[vals]
        .unstack([-1, *range(-2, -len(cols)-2, -1)], fill_value=0)
    )
    df1 = df1.set_axis([f"{c[0]}_{c[1]}" for c in df1], axis=1).reset_index()
    
  • minimum case using the set_index + unstack syntax:

    case3

    Code:

    df1 = df.set_index(['A', df.groupby('A').cumcount()])['E'].unstack(fill_value=0).add_prefix('Col').reset_index()
    

1 pivot_table() aggregates the values and unstacks it. Specifically, it creates a single flat list out of index and columns, calls groupby() with this list as the grouper and aggregates using the passed aggregator methods (the default is mean). Then after aggregation, it calls unstack() by the list of columns. So internally, pivot_table = groupby + unstack. Moreover, if fill_value is passed, fillna() is called.

In other words, the method that produces pv_1 is the same as the method that produces gb_1 in the example below.

pv_1 = df.pivot_table(index=rows, columns=cols, values=vals, aggfunc=aggfuncs, fill_value=0)
# internal operation of `pivot_table()`
gb_1 = df.groupby(rows+cols)[vals].agg(aggfuncs).unstack(cols).fillna(0, downcast="infer")
pv_1.equals(gb_1) # True

2 crosstab() calls pivot_table(), i.e., crosstab = pivot_table. Specifically, it builds a DataFrame out of the passed arrays of values, filters it by the common indices and calls pivot_table(). It's more limited than pivot_table() because it only allows a one-dimensional array-like as values, unlike pivot_table() that can have multiple columns as values.

我偏爱纯白色 2025-01-22 13:18:44

pandas中的pivot函数与excel中的pivot操作具有相同的功能。我们可以将数据集从长格式转换为宽格式。

输入图片此处描述

让我们看一个示例

在此处输入图像描述

我们希望将数据集转换为一种形式,使每个国家成为一列,并且新确认案例作为与国家相对应的值。我们可以使用数据透视函数执行此数据操作。

输入图片此处的描述

透视数据集

pivot_df = pd.pivot(df, index =['Date'], columns ='Country', values =['NewConfirmed'])
## renaming the columns  
pivot_df.columns = df['Country'].sort_values().unique()

我们可以通过重置索引将新列置于与索引列 Data 相同的级别。

重置索引以修改列级别

ivot_df =ivot_df.reset_index()

在此处输入图像描述

The pivot function in pandas has the same functionality as the pivot operation in excel. We can transform a dataset from a long format to a wide format.

enter image description here

Lets have a example

enter image description here

We want to convert the dataset into a form such that each country becomes a column and the new confirmed cases as values corresponding to the countries. We can perform this data manipulation using the pivot function.

enter image description here

Pivot the dataset

pivot_df = pd.pivot(df, index =['Date'], columns ='Country', values =['NewConfirmed'])
## renaming the columns  
pivot_df.columns = df['Country'].sort_values().unique()

We can bring the new columns to the same level as the index column Data by resetting the index.

reset the index to modify the column levels

pivot_df = pivot_df.reset_index()

enter image description here

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文