23  Pandas - inne

23.1 Uzupełnianie braków

import pandas as pd

s = pd.Series([3, -5, 7, 4], index=['a', 'b', 'c', 'd'])
s2 = pd.Series([7, -2, 3], index=['a', 'c', 'd'])
print(s + s2)
print("--")
print(s.add(s2, fill_value=0))
print("--")
print(s.mul(s2, fill_value=2))
a    10.0
b     NaN
c     5.0
d     7.0
dtype: float64
--
a    10.0
b    -5.0
c     5.0
d     7.0
dtype: float64
--
a    21.0
b   -10.0
c   -14.0
d    12.0
dtype: float64

23.2 Obsługa brakujących danych

import numpy as np
import pandas as pd

string_data = pd.Series(['aardvark', 'artichoke', np.nan, 'avocado'])
print(string_data)
print(string_data.isna())
print(string_data.dropna())
0     aardvark
1    artichoke
2          NaN
3      avocado
dtype: object
0    False
1    False
2     True
3    False
dtype: bool
0     aardvark
1    artichoke
3      avocado
dtype: object

from numpy import nan as NA
import pandas as pd

data = pd.DataFrame([[1., 6.5, 3.], [1., NA, NA],
                     [NA, NA, NA], [NA, 6.5, 3.]])
cleaned = data.dropna()
print(cleaned)
print(data.dropna(how='all'))
data[4] = NA
print(data.dropna(how='all', axis=1))
print(data)
print(data.fillna(0))
print(data.fillna({1: 0.5, 2: 0}))
     0    1    2
0  1.0  6.5  3.0
     0    1    2
0  1.0  6.5  3.0
1  1.0  NaN  NaN
3  NaN  6.5  3.0
     0    1    2
0  1.0  6.5  3.0
1  1.0  NaN  NaN
2  NaN  NaN  NaN
3  NaN  6.5  3.0
     0    1    2   4
0  1.0  6.5  3.0 NaN
1  1.0  NaN  NaN NaN
2  NaN  NaN  NaN NaN
3  NaN  6.5  3.0 NaN
     0    1    2    4
0  1.0  6.5  3.0  0.0
1  1.0  0.0  0.0  0.0
2  0.0  0.0  0.0  0.0
3  0.0  6.5  3.0  0.0
     0    1    2   4
0  1.0  6.5  3.0 NaN
1  1.0  0.5  0.0 NaN
2  NaN  0.5  0.0 NaN
3  NaN  6.5  3.0 NaN

23.3 Usuwanie duplikatów

import pandas as pd

data = pd.DataFrame({'k1': ['one', 'two'] * 3 + ['two'],
                     'k2': [1, 1, 2, 3, 3, 4, 4]})
print(data)
print(data.duplicated())
print(data.drop_duplicates())
    k1  k2
0  one   1
1  two   1
2  one   2
3  two   3
4  one   3
5  two   4
6  two   4
0    False
1    False
2    False
3    False
4    False
5    False
6     True
dtype: bool
    k1  k2
0  one   1
1  two   1
2  one   2
3  two   3
4  one   3
5  two   4

23.4 Zastępowanie wartościami

import pandas as pd
import numpy as np

data = pd.Series([1., -999., 2., -999., -1000., 3.])
print(data)
print(data.replace(-999, np.nan))
print(data.replace([-999, -1000], np.nan))
print(data.replace([-999, -1000], [np.nan, 0]))
print(data.replace({-999: np.nan, -1000: 0}))
0       1.0
1    -999.0
2       2.0
3    -999.0
4   -1000.0
5       3.0
dtype: float64
0       1.0
1       NaN
2       2.0
3       NaN
4   -1000.0
5       3.0
dtype: float64
0    1.0
1    NaN
2    2.0
3    NaN
4    NaN
5    3.0
dtype: float64
0    1.0
1    NaN
2    2.0
3    NaN
4    0.0
5    3.0
dtype: float64
0    1.0
1    NaN
2    2.0
3    NaN
4    0.0
5    3.0
dtype: float64

23.5 Dyskretyzacja i podział na koszyki

import pandas as pd

ages = [20, 22, 25, 27, 21, 23, 37, 31, 61, 45, 41, 32]
bins = [18, 25, 35, 60, 100]
cats = pd.cut(ages, bins)
print(cats)
print(cats.codes)
print(cats.categories)
print(pd.Series(cats).value_counts())
[(18, 25], (18, 25], (18, 25], (25, 35], (18, 25], ..., (25, 35], (60, 100], (35, 60], (35, 60], (25, 35]]
Length: 12
Categories (4, interval[int64, right]): [(18, 25] < (25, 35] < (35, 60] < (60, 100]]
[0 0 0 1 0 0 2 1 3 2 2 1]
IntervalIndex([(18, 25], (25, 35], (35, 60], (60, 100]], dtype='interval[int64, right]')
(18, 25]     5
(25, 35]     3
(35, 60]     3
(60, 100]    1
Name: count, dtype: int64

import pandas as pd

ages = [20, 22, 25, 27, 21, 23, 37, 31, 61, 45, 41, 32]
bins = [18, 25, 35, 60, 100]
cats2 = pd.cut(ages, [18, 26, 36, 61, 100], right=False)
print(cats2)
group_names = ['Youth', 'YoungAdult',
               'MiddleAged', 'Senior']
print(pd.cut(ages, bins, labels=group_names))
[[18, 26), [18, 26), [18, 26), [26, 36), [18, 26), ..., [26, 36), [61, 100), [36, 61), [36, 61), [26, 36)]
Length: 12
Categories (4, interval[int64, left]): [[18, 26) < [26, 36) < [36, 61) < [61, 100)]
['Youth', 'Youth', 'Youth', 'YoungAdult', 'Youth', ..., 'YoungAdult', 'Senior', 'MiddleAged', 'MiddleAged', 'YoungAdult']
Length: 12
Categories (4, object): ['Youth' < 'YoungAdult' < 'MiddleAged' < 'Senior']

import pandas as pd
import numpy as np

data = np.random.rand(20)
print(pd.cut(data, 4, precision=2))
[(0.28, 0.51], (0.74, 0.97], (0.74, 0.97], (0.51, 0.74], (0.051, 0.28], ..., (0.74, 0.97], (0.051, 0.28], (0.74, 0.97], (0.051, 0.28], (0.051, 0.28]]
Length: 20
Categories (4, interval[float64, right]): [(0.051, 0.28] < (0.28, 0.51] < (0.51, 0.74] < (0.74, 0.97]]

import pandas as pd
import numpy as np

data = np.random.randn(1000)
cats = pd.qcut(data, 4)
print(cats)
print(pd.Series(cats).value_counts())
[(0.01, 0.697], (-2.997, -0.675], (-0.675, 0.01], (0.01, 0.697], (0.697, 3.232], ..., (-0.675, 0.01], (-2.997, -0.675], (-2.997, -0.675], (-0.675, 0.01], (0.697, 3.232]]
Length: 1000
Categories (4, interval[float64, right]): [(-2.997, -0.675] < (-0.675, 0.01] < (0.01, 0.697] < (0.697, 3.232]]
(-2.997, -0.675]    250
(-0.675, 0.01]      250
(0.01, 0.697]       250
(0.697, 3.232]      250
Name: count, dtype: int64

23.6 Wykrywanie i filtrowanie elementów odstających

import pandas as pd
import numpy as np

data = pd.DataFrame(np.random.randn(1000, 4))
print(data.describe())
print("---")
col = data[2]
print(col[np.abs(col) > 3])
print("---")
print(data[(np.abs(data) > 3).any(axis=1)])
                 0            1            2            3
count  1000.000000  1000.000000  1000.000000  1000.000000
mean      0.054278     0.015697    -0.030640    -0.025036
std       1.014273     1.032012     1.042003     0.957561
min      -2.867766    -3.648096    -3.473948    -3.582081
25%      -0.596976    -0.634695    -0.744587    -0.664974
50%       0.060153     0.035933    -0.053565    -0.037836
75%       0.747286     0.701091     0.631552     0.635125
max       2.977282     3.161138     2.811008     3.662363
---
522   -3.473948
726   -3.331977
Name: 2, dtype: float64
---
            0         1         2         3
47   0.179807  1.244742  0.781058 -3.582081
212 -0.326314 -0.621330 -0.250702 -3.365875
301  1.265376  3.129287  0.971621  0.296440
469  0.260206  3.161138 -1.822953 -1.008064
522 -0.146252  1.353971 -3.473948  0.462879
526 -1.824789  0.626713  1.541883 -3.220135
600 -0.191144 -3.017049  0.359821  0.088797
674 -1.843046  0.393338 -2.209780  3.662363
726 -0.561976 -0.543376 -3.331977 -0.001821
844 -0.972283 -3.648096 -0.066647  0.302503
930 -0.464239  3.105804 -0.662495  0.080488

23.7 Zmiana typu w kolumnie

import pandas as pd


data = {
    'A': ['1', '2', '3', '4', '5', '6'],
    'B': ['7.5', '8.5', '9.5', '10.5', '11.5', '12.5'],
    'C': ['x', 'y', 'z', 'x', 'y', 'z']
}
data2 = pd.DataFrame(data)

# Wyświetlenie oryginalnej ramki danych
print("Oryginalna ramka danych:")
print(data2)

# Zmiana typu danych kolumny 'A' na int
data2['A'] = pd.Series(data2['A'], dtype=int)

# Zmiana typu danych kolumny 'B' na float
data2['B'] = pd.Series(data2['A'], dtype=float)

# Wyświetlenie ramki danych po zmianie typów
print("\nRamka danych po zmianie typów:")
print(data2)
Oryginalna ramka danych:
   A     B  C
0  1   7.5  x
1  2   8.5  y
2  3   9.5  z
3  4  10.5  x
4  5  11.5  y
5  6  12.5  z

Ramka danych po zmianie typów:
   A    B  C
0  1  1.0  x
1  2  2.0  y
2  3  3.0  z
3  4  4.0  x
4  5  5.0  y
5  6  6.0  z
import pandas as pd


data = {
    'A': ['1', '2', '3', '4', '5', '6'],
    'B': ['7.5', '8.5', '9.5', '10.5', '11.5', '12.5'],
    'C': ['x', 'y', 'z', 'x', 'y', 'z']
}
data2 = pd.DataFrame(data)

# Wyświetlenie oryginalnej ramki danych
print("Oryginalna ramka danych:")
print(data2)

# Zmiana typu danych kolumny 'A' na int
data2['A'] = data2['A'].astype(int)

# Zmiana typu danych kolumny 'B' na float
data2['B'] = data2['B'].astype(float)

# Wyświetlenie ramki danych po zmianie typów
print("\nRamka danych po zmianie typów:")
print(data2)
Oryginalna ramka danych:
   A     B  C
0  1   7.5  x
1  2   8.5  y
2  3   9.5  z
3  4  10.5  x
4  5  11.5  y
5  6  12.5  z

Ramka danych po zmianie typów:
   A     B  C
0  1   7.5  x
1  2   8.5  y
2  3   9.5  z
3  4  10.5  x
4  5  11.5  y
5  6  12.5  z

23.8 Zmiana znaku kategoriach

import pandas as pd

# Tworzenie ramki danych
data = {
    'A': ['abc', 'def', 'ghi', 'jkl', 'mno', 'pqr'],
    'B': ['1.23', '4.56', '7.89', '0.12', '3.45', '6.78'],
    'C': ['xyz', 'uvw', 'rst', 'opq', 'lmn', 'ijk']
}
data2 = pd.DataFrame(data)

# Wyświetlenie oryginalnej ramki danych
print("Oryginalna ramka danych:")
print(data2)

# Zmiana małych liter na duże w kolumnie 'A'
data2['A'] = data2['A'].str.upper()

# Zastąpienie kropki przecinkiem w kolumnie 'B'
data2['B'] = data2['B'].str.replace('.', ',')

# Wyświetlenie ramki danych po modyfikacji
print("\nRamka danych po modyfikacji:")
print(data2)
Oryginalna ramka danych:
     A     B    C
0  abc  1.23  xyz
1  def  4.56  uvw
2  ghi  7.89  rst
3  jkl  0.12  opq
4  mno  3.45  lmn
5  pqr  6.78  ijk

Ramka danych po modyfikacji:
     A     B    C
0  ABC  1,23  xyz
1  DEF  4,56  uvw
2  GHI  7,89  rst
3  JKL  0,12  opq
4  MNO  3,45  lmn
5  PQR  6,78  ijk

23.9 Operacje manipulacyjne

Ściągawka https://pandas.pydata.org/Pandas_Cheat_Sheet.pdf

  • merge

https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.merge.html

Funkcja merge służy do łączenia dwóch ramek danych wzdłuż wspólnej kolumny, podobnie jak operacje JOIN w SQL.

DataFrame.merge(right, how='inner', on=None, left_on=None, right_on=None,
                left_index=False, right_index=False, sort=False,
                suffixes=('_x', '_y'), copy=True, indicator=False, validate=None)

Gdzie:

  • right: ramka danych, którą chcesz dołączyć do oryginalnej ramki danych.
  • how: określa typ łączenia. Dostępne są cztery typy: ‘inner’, ‘outer’, ‘left’ i ‘right’. ‘inner’ to domyślna wartość, która zwraca tylko te wiersze, które mają pasujące klucze w obu ramkach danych.
  • on: nazwa lub lista nazw, które mają być używane do łączenia. Musi to być nazwa występująca zarówno w oryginalnej, jak i prawej ramce danych.
  • left_on i right_on: nazwy kolumn w lewej i prawej ramce danych, które mają być używane do łączenia. Można to użyć, jeśli nazwy kolumn nie są takie same.
  • left_index i right_index: czy indeksy z lewej i prawej ramki danych mają być używane do łączenia.
  • sort: czy wynikowa ramka danych ma być posortowany według łączonych kluczy.
  • suffixes: sufiksy, które mają być dodane do nazw kolumn, które nachodzą na siebie. Domyślnie to (’_x’, ’_y’).
  • copy: czy zawsze kopiować dane, nawet jeśli nie są potrzebne.
  • indicator: dodaj kolumnę do wynikowej ramki danych, która pokazuje źródło każdego wiersza.
  • validate: sprawdź, czy określone zasady łączenia są spełnione.
import pandas as pd

df1 = pd.DataFrame({
    'A': ['A0', 'A1', 'A2', 'A3'],
    'B': ['B0', 'B1', 'B2', 'B3'],
    'key': ['K0', 'K1', 'K0', 'K1']
})

df2 = pd.DataFrame({
    'C': ['C0', 'C1'],
    'D': ['D0', 'D1']},
    index=['K0', 'K1']
)

print(df1)
print(df2)
merged_df = df1.merge(df2, left_on='key', right_index=True)
print(merged_df)
    A   B key
0  A0  B0  K0
1  A1  B1  K1
2  A2  B2  K0
3  A3  B3  K1
     C   D
K0  C0  D0
K1  C1  D1
    A   B key   C   D
0  A0  B0  K0  C0  D0
1  A1  B1  K1  C1  D1
2  A2  B2  K0  C0  D0
3  A3  B3  K1  C1  D1

import pandas as pd

df1 = pd.DataFrame({
    'key': ['K0', 'K1', 'K2', 'K3'],
    'A': ['A0', 'A1', 'A2', 'A3'],
    'B': ['B0', 'B1', 'B2', 'B3']
})

df2 = pd.DataFrame({
    'key': ['K0', 'K1', 'K4', 'K5'],
    'C': ['C0', 'C1', 'C2', 'C3'],
    'D': ['D0', 'D1', 'D2', 'D3']
})

print(df1)

print(df2)

inner_merged_df = df1.merge(df2, how='inner', on='key', suffixes=('_left', '_right'),
                            indicator=True)
outer_merged_df = df1.merge(df2, how='outer', on='key', suffixes=('_left', '_right'),
                            indicator=True)
left_merged_df = df1.merge(df2, how='left', on='key', suffixes=('_left', '_right'),
                           indicator=True)
right_merged_df = df1.merge(df2, how='right', on='key', suffixes=('_left', '_right'),
                            indicator=True)

print("Inner join")
print(inner_merged_df)

print("Outer join")
print(outer_merged_df)

print("Left join")
print(left_merged_df)

print("Right join")
print(right_merged_df)
  key   A   B
0  K0  A0  B0
1  K1  A1  B1
2  K2  A2  B2
3  K3  A3  B3
  key   C   D
0  K0  C0  D0
1  K1  C1  D1
2  K4  C2  D2
3  K5  C3  D3
Inner join
  key   A   B   C   D _merge
0  K0  A0  B0  C0  D0   both
1  K1  A1  B1  C1  D1   both
Outer join
  key    A    B    C    D      _merge
0  K0   A0   B0   C0   D0        both
1  K1   A1   B1   C1   D1        both
2  K2   A2   B2  NaN  NaN   left_only
3  K3   A3   B3  NaN  NaN   left_only
4  K4  NaN  NaN   C2   D2  right_only
5  K5  NaN  NaN   C3   D3  right_only
Left join
  key   A   B    C    D     _merge
0  K0  A0  B0   C0   D0       both
1  K1  A1  B1   C1   D1       both
2  K2  A2  B2  NaN  NaN  left_only
3  K3  A3  B3  NaN  NaN  left_only
Right join
  key    A    B   C   D      _merge
0  K0   A0   B0  C0  D0        both
1  K1   A1   B1  C1  D1        both
2  K4  NaN  NaN  C2  D2  right_only
3  K5  NaN  NaN  C3  D3  right_only

  • join

https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.join.html

Metoda join jest używana do łączenia dwóch ramek danych wzdłuż osi.

Podstawowe użycie tej metody wygląda następująco:

DataFrame.join(other, on=None, how='left', lsuffix='', rsuffix='', sort=False)

Gdzie:

  • other: ramka danych, którą chcesz dołączyć do oryginalnej ramki danych.
  • on: nazwa lub lista nazw kolumn w oryginalnej ramxce danych, do których chcesz dołączyć.
  • how: określa typ łączenia. Dostępne są cztery typy: ‘inner’, ‘outer’, ‘left’ i ‘right’. ‘left’ to domyślna wartość, która zwraca wszystkie wiersze z oryginalnej ramki danych i pasujące wiersze z drugiej ramki danych. Wartości są uzupełniane wartością NaN, jeśli nie ma dopasowania.
  • lsuffix i rsuffix: sufiksy do dodania do kolumn, które się powtarzają. Domyślnie jest to puste.
  • sort: czy sortować dane według klucza.
import pandas as pd

df1 = pd.DataFrame({
    'A': ['A0', 'A1', 'A2'],
    'B': ['B0', 'B1', 'B2']},
    index=['K0', 'K1', 'K2']
)

df2 = pd.DataFrame({
    'C': ['C0', 'C2', 'C3'],
    'D': ['D0', 'D2', 'D3']},
    index=['K0', 'K2', 'K3']
)

print(df1)

print(df2)

joined_df = df1.join(df2)
print(joined_df)
     A   B
K0  A0  B0
K1  A1  B1
K2  A2  B2
     C   D
K0  C0  D0
K2  C2  D2
K3  C3  D3
     A   B    C    D
K0  A0  B0   C0   D0
K1  A1  B1  NaN  NaN
K2  A2  B2   C2   D2

  • concat

https://pandas.pydata.org/docs/reference/api/pandas.concat.html

Metoda concat jest używana do łączenia dwóch lub więcej ramek danych wzdłuż określonej osi.

Podstawowe użycie tej metody wygląda następująco:

pandas.concat(objs, axis=0, join='outer', ignore_index=False, keys=None,
              levels=None, names=None, verify_integrity=False, sort=False,
              copy=True)

Gdzie:

  • objs: sekwencja ramek danych, które chcesz połączyć.
  • axis: oś, wzdłuż której chcesz łączyć ramki danych. Domyślnie to 0 (łączenie wierszy, pionowo), ale można także ustawić na 1 (łączenie kolumn, poziomo).
  • join: określa typ łączenia. Dostępne są dwa typy: ‘outer’ i ‘inner’. ‘outer’ to domyślna wartość, która zwraca wszystkie kolumny z każdej ramki danych. ‘inner’ zwraca tylko te kolumny, które są wspólne dla wszystkich ramek danych.
  • ignore_index: jeśli ustawione na True, nie używa indeksów z ramek danych do tworzenia indeksu w wynikowej ramce danych. Zamiast tego tworzy nowy indeks od 0 do n-1.
  • keys: wartości do skojarzenia z obiektami.
  • levels: określone indeksy dla nowej ramki danych.
  • names: nazwy dla poziomów indeksów (jeśli są wielopoziomowe).
  • verify_integrity: sprawdza, czy nowy, skonkatenowana ramka danych nie ma powtarzających się indeksów.
  • sort: czy sortować niekonkatenacyjną oś (np. indeksy, jeśli axis=0), niezależnie od danych.
  • copy: czy zawsze kopiować dane, nawet jeśli nie są potrzebne.
import pandas as pd

df1 = pd.DataFrame({
    'A': ['A0', 'A1', 'A2'],
    'B': ['B0', 'B1', 'B2']
})

df2 = pd.DataFrame({
    'A': ['A3', 'A4', 'A5'],
    'B': ['B3', 'B4', 'B5']
})

print(df1)

print(df2)

concatenated_df = pd.concat([df1, df2], ignore_index=True)
print(concatenated_df)
    A   B
0  A0  B0
1  A1  B1
2  A2  B2
    A   B
0  A3  B3
1  A4  B4
2  A5  B5
    A   B
0  A0  B0
1  A1  B1
2  A2  B2
3  A3  B3
4  A4  B4
5  A5  B5

import pandas as pd

df1 = pd.DataFrame({
    'A': ['A0', 'A1', 'A2'],
    'B': ['B0', 'B1', 'B2']
})

df2 = pd.DataFrame({
    'C': ['C0', 'C1', 'C2'],
    'D': ['D0', 'D1', 'D2']
})

print(df1)

print(df2)

concatenated_df_axis1 = pd.concat([df1, df2], axis=1)
concatenated_df_keys = pd.concat([df1, df2], keys=['df1', 'df2'])

print(concatenated_df_axis1)
print(concatenated_df_keys)
    A   B
0  A0  B0
1  A1  B1
2  A2  B2
    C   D
0  C0  D0
1  C1  D1
2  C2  D2
    A   B   C   D
0  A0  B0  C0  D0
1  A1  B1  C1  D1
2  A2  B2  C2  D2
         A    B    C    D
df1 0   A0   B0  NaN  NaN
    1   A1   B1  NaN  NaN
    2   A2   B2  NaN  NaN
df2 0  NaN  NaN   C0   D0
    1  NaN  NaN   C1   D1
    2  NaN  NaN   C2   D2

  • pivot

https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.pivot.html

Metoda pivot jest używana do przekształcenia danych z formatu “długiego” do “szerokiego”.

Podstawowe użycie tej metody wygląda następująco:

DataFrame.pivot(index=None, columns=None, values=None)

Gdzie:

  • index: nazwa kolumny lub lista nazw kolumn, które mają stać się indeksem w nowej ramce danych.
  • columns: nazwa kolumny, z której unikalne wartości mają stać się kolumnami w nowej ramce danych.
  • values: nazwa kolumny lub lista nazw kolumn, które mają stać się wartościami dla nowych kolumn w nowej ramce danych.
import pandas as pd

df = pd.DataFrame({
    'foo': ['one', 'one', 'one', 'two', 'two', 'two'],
    'bar': ['A', 'B', 'C', 'A', 'B', 'C'],
    'baz': [1, 2, 3, 4, 5, 6],
    'zoo': ['x', 'y', 'z', 'q', 'w', 't'],
})

print(df)

pivot_df = df.pivot(index='foo', columns='bar', values='baz')
print(pivot_df)
   foo bar  baz zoo
0  one   A    1   x
1  one   B    2   y
2  one   C    3   z
3  two   A    4   q
4  two   B    5   w
5  two   C    6   t
bar  A  B  C
foo         
one  1  2  3
two  4  5  6

  • wide_to_long

https://pandas.pydata.org/docs/reference/api/pandas.wide_to_long.html

Metoda wide_to_long jest używana do przekształcenia danych z szerokiego formatu (gdzie każda kolumna zawiera wiele zmiennych) do długiego formatu (gdzie każda kolumna zawiera jedną zmienną z wieloma pomiarami). Jest to przydatne, gdy mamy dane, które są rozłożone w wielu kolumnach z powtarzającymi się lub sekwencyjnymi nazwami, i chcemy przekształcić te dane w sposób, który ułatwia analizę i wizualizację.

Wyjaśnienie parametrów wide_to_long

  • stubnames: Lista początkowych części nazw kolumn, które mają zostać przekształcone.
  • i: Nazwa kolumny lub lista kolumn, które identyfikują poszczególne wiersze. W naszym przykładzie jest to id, które unikalnie identyfikuje osobę.
  • j: Nazwa nowej kolumny, w której będą przechowywane różne poziomy zmiennych (w naszym przypadku rok).
  • sep: Opcjonalny separator (domyślnie "").
import pandas as pd

# Przykładowe dane
data = {
    'id': ['A', 'B', 'C'],
    'height_2020': [180, 175, 165],
    'weight_2020': [70, 76, 65],
    'height_2021': [181, 176, 166],
    'weight_2021': [71, 77, 66]
}

data2 = pd.DataFrame(data)

# Przekształcenie do formatu długiego
df_long = pd.wide_to_long(data2, stubnames=['height', 'weight'], i='id', j='year', sep='_')
df_long = df_long.reset_index()

print(df_long)
  id  year  height  weight
0  A  2020     180      70
1  B  2020     175      76
2  C  2020     165      65
3  A  2021     181      71
4  B  2021     176      77
5  C  2021     166      66

  • melt

https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.melt.html

Funkcja melt służy do przekształcania danych z formatu szerokiego na długi.

Podstawowe użycie tej metody wygląda następująco:

pandas.melt(frame, id_vars=None, value_vars=None, var_name=None, value_name='value', col_level=None)

Gdzie:

  • frame: ramka danych, którą chcesz przetworzyć.
  • id_vars: kolumna(y), które chcesz zachować jako identyfikatory. Te kolumny nie będą zmieniane.
  • value_vars: kolumna(y), które chcesz przekształcić na pary klucz-wartość. Jeżeli nie jest podane, wszystkie kolumny nie będące id_vars zostaną użyte.
  • var_name: nazwa nowej kolumny, która będzie zawierała nazwy kolumn przekształconych na pary klucz-wartość. Domyślnie to ‘variable’.
  • value_name: nazwa nowej kolumny, która będzie zawierała wartości kolumn przekształconych na pary klucz-wartość. Domyślnie to ‘value’.
  • col_level: jeżeli kolumny są wielopoziomowe, to jest poziom, który będzie użyty do przekształcania kolumn na pary klucz-wartość.
import pandas as pd

data = pd.DataFrame({
    'A': ['foo', 'bar', 'baz'],
    'B': ['one', 'one', 'two'],
    'C': [2.0, 1.0, 3.0],
    'D': [3.0, 2.0, 1.0]
})
print(data)
melted_df = data.melt(id_vars=['A', 'B'], value_vars=['C', 'D'], var_name='My_Var',
                      value_name='My_Val')
print(melted_df)
     A    B    C    D
0  foo  one  2.0  3.0
1  bar  one  1.0  2.0
2  baz  two  3.0  1.0
     A    B My_Var  My_Val
0  foo  one      C     2.0
1  bar  one      C     1.0
2  baz  two      C     3.0
3  foo  one      D     3.0
4  bar  one      D     2.0
5  baz  two      D     1.0