python畫圖標題 - text plt python



如何透視數據框 (1)

  • 什麼是樞軸?
  • 如何轉動?
  • 這是一個支點嗎?
  • 長格式到寬格式?

我見過很多關於數據透視表的問題。 即使他們不知道他們詢問數據透視表,他們通常也是。 幾乎不可能寫出一個規範的問題和答案,其中包含了旋轉的所有方面....

......但是我要試一試。

現有問題和答案的問題在於,問題往往集中在OP難以概括以便使用一些現有的良好答案的細微差別。 但是,沒有一個答案試圖給出全面的解釋(因為這是一項艱鉅的任務)

從我的 谷歌搜索中 查看一些示例

  1. 如何在Pandas中透視數據框?
    • 好問答。 但答案只回答了具體問題,幾乎沒有解釋。
  2. pandas將表轉移到數據框
    • 在這個問題中,OP關注的是樞軸的輸出。 即列的外觀。 OP希望它看起來像R.這對熊貓用戶來說並不是很有幫助。
  3. pandas轉動數據框,重複行
    • 另一個不錯的問題,但答案集中在一個方法,即 pd.DataFrame.pivot

因此,每當有人搜索 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

問題(S)

  1. 為什麼我會得到 ValueError: Index contains duplicate entries, cannot reshape

  2. 如何調整 df 以使 col 值為列, row 值為索引, val0 的平均值為?

    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. 如何調整 df 以使 col 值為列, row 值為索引, val0 平均值為值,缺失值為 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. 我可以得到除了 mean 東西,比如 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. 我可以一次做多個聚合嗎?

           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. 我可以聚合多個值列嗎?

          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. 可以按多列細分嗎?

    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. 要么

    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. 我可以匯總列和行一起出現的頻率,也就是“交叉製表”嗎?

    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. 如何通過僅在兩列上旋轉將數據框架從長到寬轉換? 鑑於,

    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

    預期應該看起來像

          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. 如何在多個索引之後將多個索引展平為單個索引

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

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

我們首先回答第一個問題:

問題1

為什麼我會得到 ValueError: Index contains duplicate entries, cannot reshape

發生這種情況是因為pandas正在嘗試重新索引具有重複條目的 columnsindex 對象。 可以使用不同的方法來執行樞軸。 它們中的一些不適合於當要求其轉動的鍵的重複時。 例如。 考慮 pd.DataFrame.pivot 。 我知道有重複的條目共享 rowcol 值:

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

所以當我 pivot 使用時

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

我收到上面提到的錯誤。 事實上,當我嘗試執行相同的任務時,我得到了同樣的錯誤:

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

這是我們可以用來轉動的習語列表

  1. pd.DataFrame.groupby + pd.DataFrame.unstack
    • 做任何類型的樞軸的良好通用方法
    • 您可以指定將構成一個組中的透視行級別和列級別的所有列。 您可以通過選擇要聚合的剩餘列以及要執行聚合的功能來執行此操作。 最後,您將要 unstack 列索引中的級別。
  2. pd.DataFrame.pivot_table
    • 具有更直觀API的 groupby 的美化版本。 對於許多人來說,這是首選方法。 並且是開發人員的預期方法。
    • 指定行級別,列級別,要聚合的值以及執行聚合的函數。
  3. pd.DataFrame.set_index + pd.DataFrame.unstack
    • 一些方便直觀(包括我自己)。 無法處理重複的分組鍵。
    • groupby 範例類似,我們指定最終將是行級別或列級別的所有列,並將這些列設置為索引。 然後,我們在列中 unstack 我們想要的級別。 如果其餘索引級別或列級別不唯一,則此方法將失敗。
  4. pd.DataFrame.pivot
    • set_index 非常相似,因為它共享重複鍵限制。 API也非常有限。 它只需要 indexcolumnsvaluesvalues
    • pivot_table 方法類似,我們選擇要轉動的行,列和值。 但是,我們無法聚合,如果行或列不唯一,則此方法將失敗。
  5. pd.crosstab
    • 這是 pivot_table 的專用版本,並且以最純粹的形式是執行多個任務的最直觀方式。
  6. pd.factorize + np.bincount
    • 這是一種非常先進但非常快速的非常先進的技術。 它不能在所有情況下使用,但是當它可以使用並且您習慣使用它時,您將獲得性能獎勵。
  7. pd.get_dummies + pd.DataFrame.dot
    • 我用它來巧妙地執行交叉製表。

例子

我將為每個後續答案和問題做的是使用 pd.DataFrame.pivot_table 來回答它。 然後我將提供執行相同任務的替代方案。

問題3

如何調整 df 以使 col 值為列, row 值為索引, val0 平均值為值,缺失值為 0

  • pd.DataFrame.pivot_table

    • 默認情況下未設置 fill_value 。 我傾向於適當地設置它。 在這種情況下,我將其設置為 0 。 注意我跳過 問題2, 因為它與沒有 fill_value 答案相同
    • aggfunc='mean' 是默認值,我沒有必要設置它。 我把它包括在內是明確的。

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

    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.crosstab

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

問題4

我可以得到除了 mean 東西,比如 sum 嗎?

  • pd.DataFrame.pivot_table

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

    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.crosstab

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

問題5

我可以一次做多個聚合嗎?

請注意,對於 pivot_tablecross_tab 我需要傳遞callables列表。 另一方面, groupby.agg 能夠為有限數量的特殊函數獲取字符串。 groupby.agg 也會採用我們傳遞給其他人的相同callables,但是利用字符串函數名稱通常更有效,因為可以獲得效率。

  • pd.DataFrame.pivot_table

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

    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.crosstab

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

問題6

我可以聚合多個值列嗎?

  • pd.DataFrame.pivot_table 我們傳遞的 values=['val0', 'val1'] 但我們可以完全離開

    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)

問題7

可以按多列細分嗎?

  • 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)

問題8

可以按多列細分嗎?

  • pd.DataFrame.pivot_table

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

    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.set_index 因為鍵集對於行和列都是唯一的

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

問題9

我可以匯總列和行一起出現的頻率,也就是“交叉製表”嗎?

  • pd.DataFrame.pivot_table

    pd.crosstab(df['row'], df['col'])
  • pd.DataFrame.groupby

    # 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.cross_tab

    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
  • pd.factorize + np.bincount

    df2.insert(0, 'count', df.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
  • pd.get_dummies

    df2.pivot(*df)
    # df.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

問題10

如何通過僅在兩列上旋轉將數據框架從長到寬轉換?

第一步是為每一行分配一個數字 - 該數字將是旋轉結果中該值的行索引。 這是使用 GroupBy.cumcount 完成的:

df2.assign(count=df.groupby('A').cumcount()).pivot('count', 'A', 'B')

A         a     b    c
count                 
0      12.0  11.0  9.0
1       5.0   3.0  NaN
2       0.0   7.0  NaN
3       3.0   NaN  NaN

問題11

如何在多個索引之後將多個索引展平為單個索引

如果 columns 鍵入帶字符串 join object

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

其他 format

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




pandas-groupby