Jak obrócić ramkę danych

  • Co to jest pivot?
  • Jak się obracać?
  • czy to pivot?
  • długi format do szerokiego formatu?

Widziałem wiele pytań, które pytają o tabele przestawne. Nawet jeśli nie wiedzą, że pytają o tabele przestawne, zwykle tak jest. Jest to praktycznie niemożliwe, aby napisać kanoniczne pytanie i odpowiedź, która obejmuje wszystkie aspekty obrotu....

... Ale spróbuję.


Problem z istniejącymi pytania i odpowiedzi jest to, że często pytanie koncentruje się na niuansie, że OP ma problemy uogólniania w celu wykorzystania wielu istniejących dobrych odpowiedzi. Jednak żadna z odpowiedzi nie próbuje dać wyczerpującego wyjaśnienia (ponieważ jest to trudne zadanie) [34]}

Spójrz na kilka przykładów z mojego szukaj w google

  1. jak obracać ramkę danych w pandach?
    • dobre pytanie i odpowiedź. Ale odpowiedź odpowiada tylko na konkretne pytanie z małym wyjaśnieniem.
  2. tabela przestawna pandy do ramki danych
    • W tym pytaniu OP dotyczy wyjścia Pivota. Mianowicie jak wyglądają kolumny. OP chciał, żeby wyglądało jak R. nie jest to zbyt pomocne dla użytkowników pand.
  3. pandy obracają ramkę danych, powielają wiersze
    • kolejne porządne pytanie, ale odpowiedź skupia się na jednej metodzie, a mianowicie pd.DataFrame.pivot

Więc za każdym razem, gdy ktoś szuka pivot otrzymuje sporadyczne wyniki, które prawdopodobnie nie odpowiedzą na jego konkretne pytanie.


Setup

Możesz zauważyć, że widocznie nazwałem moje kolumny i odpowiednie wartości kolumn, aby odpowiadały temu, jak będę się obracał w odpowiedziach poniżej. Zwróć uwagę, aby zapoznać się z tym, gdzie znajdują się nazwy kolumn, aby uzyskać wyniki, których szukasz za.

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

Pytanie(y)

  1. Dlaczego dostaję ValueError: Index contains duplicate entries, cannot reshape

  2. Jak obrócić df tak, aby col wartości były kolumnami, row wartości są indeksem, a średnia z val0 wartościami?

    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. Jak obrócić df tak, aby col wartości były kolumnami, row wartości są indeksem, średnia z {[15] } są wartościami, a brakujące wartości to 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. Czy Mogę dostać coś innego niż mean, Jak Może 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. Czy Mogę zrobić więcej, że jedna agregacja na raz?

           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. Czy Mogę agregować wiele kolumn wartości?

          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. Czy można podzielić na kilka kolumn?

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

    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. Czy Mogę połączyć częstotliwość, w której kolumny i wiersze występują razem, aka "tabulacja krzyżowa"?

    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
    
Author: piRSquared, 2017-11-07

1 answers

Zaczynamy od odpowiedzi na pierwsze pytanie:

Pytanie 1

Dlaczego dostaję ValueError: Index contains duplicate entries, cannot reshape

Dzieje się tak, ponieważ pandy próbują reindeksować obiekt columns lub index z duplikatami wpisów. Istnieją różne metody, które mogą wykonać obrót. Niektóre z nich nie są dobrze dostosowane do sytuacji, gdy istnieją duplikaty kluczy, w których jest proszony o obracanie się. Na przykład. Rozważ pd.DataFrame.pivot. Wiem, że są duplikaty wpisów, które dzielą wartości row i col:

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

True

Więc kiedy pivot używam

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

Dostaję błąd wymieniony powyżej. W rzeczywistości, dostaję ten sam błąd, gdy próbuję wykonać to samo zadanie z:

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

Oto lista idiomów, których możemy użyć do obracania

  1. pd.DataFrame.groupby + pd.DataFrame.unstack
      [108]}dobre ogólne podejście do robienia prawie każdego rodzaju pivot
  2. podajesz wszystkie kolumny, które będą stanowić obracane poziomy wierszy i poziomów kolumn w jednej grupie przez. Następnie zaznaczając pozostałe kolumny, które chcesz agregować, oraz funkcje, które chcesz wykonać agregację. Na koniec, można unstack poziomy, które chcesz być w indeksie kolumny.
  3. pd.DataFrame.pivot_table
    • gloryfikowana wersja groupby z bardziej intuicyjnym API. Dla wielu osób jest to preferowane podejście. I jest zamierzonym podejściem przez deweloperzy.
    • określa poziom wiersza, poziomy kolumn, wartości do agregacji oraz funkcje do agregacji.
  4. pd.DataFrame.set_index + pd.DataFrame.unstack
    • wygodne i intuicyjne dla niektórych (w tym mnie). Nie można obsługiwać zduplikowanych kluczy zgrupowanych.
    • podobnie jak paradygmat groupby, określamy wszystkie kolumny, które będą w końcu poziomami wierszy lub kolumn i ustawiamy je jako indeks. My wtedy unstack poziomy, które chcemy w kolumnach. Jeśli pozostałe poziomy indeksów lub kolumny nie są unikalne, ta metoda nie powiedzie się.
  5. pd.DataFrame.pivot
    • bardzo podobny do set_index w tym, że dzieli ograniczenie duplikatu klucza. Interfejs API jest również bardzo ograniczony. Przyjmuje tylko wartości skalarne dla index, columns, values.
    • podobne do metody pivot_table, w której wybieramy wiersze, kolumny i wartości, na których mamy się obracać. Jednak my nie można agregować i jeśli wiersze lub kolumny nie są unikalne, ta metoda nie powiedzie się.
  6. pd.crosstab
    • to wyspecjalizowana wersja pivot_table i w najczystszej formie jest najbardziej intuicyjnym sposobem wykonywania kilku zadań.
  7. pd.factorize + np.bincount
      Jest to bardzo zaawansowana technika, która jest bardzo niejasna, ale bardzo szybka. Nie może być stosowany w wszystkie okoliczności, ale kiedy można go używać i wygodnie z niego korzystać, będziesz czerpać korzyści z wydajności.
  8. pd.get_dummies + pd.DataFrame.dot
    • używam tego do sprytnego wykonywania tabulacji krzyżowej.

Przykłady

To, co zamierzam zrobić dla każdej kolejnej odpowiedzi i pytania, to odpowiedzieć za pomocą pd.DataFrame.pivot_table. Następnie dostarczę alternatywy do wykonania to samo zadanie.

Pytanie 3

Jak obrócić df tak, aby col wartości były kolumnami, row wartości są indeksem, średnia z val0 są wartościami, a brakujące wartości to 0?

  • pd.DataFrame.pivot_table

    • fill_value nie jest ustawiona domyślnie. Zazwyczaj ustawiam je odpowiednio. W tym przypadku ustawiłem go na 0. Zauważ, że pominąłem pytanie 2 ponieważ jest to to samo co ta odpowiedź bez fill_value
    • aggfunc='mean' jest domyślne i nie musiałem go ustawiać. Dodałem to, żeby było jasne.

      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)
    

Pytanie 4

Czy Mogę dostać coś innego niż mean, jak może {66]}?

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

Pytanie 5

Czy Mogę zrobić więcej, że jedna agregacja na raz?

Zauważ, że dla pivot_table i cross_tab musiałem przekazać listę połączeń. Z drugiej strony groupby.agg jest w stanie pobierać łańcuchy dla ograniczonej liczby funkcji specjalnych. groupby.agg wziąłby również te same wywołania, które przekazaliśmy innym, ale często bardziej wydajne jest wykorzystanie nazw funkcji łańcuchowych, ponieważ istnieją wydajności, które mają być / align = "left" /

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

Pytanie 6

Czy Mogę agregować wiele kolumn wartości?

  • pd.DataFrame.pivot_table mijamy values=['val0', 'val1'] ale mogliśmy to całkowicie pominąć

    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)
    

Pytanie 7

Można podzielić przez wiele kolumny?

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

Pytanie 8

Czy można podzielić przez wiele kolumn?

  • 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 ponieważ zestaw kluczy jest unikalny zarówno dla wierszy, jak i kolumn

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

Pytanie 9

Czy Mogę połączyć częstotliwość, w której kolumny i wiersze występują razem, aka "tabulacja krzyżowa"?

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

    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
    
 141
Author: piRSquared,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-14 17:13:35