Pandas 行列轉換
1.pivot_table
創建一個電子表格風格的數據透視表作為數據幀。
數據透視表中的級別將存儲在結果DataFrame的索引和列上的MultiIndex對象(分層索引)中。
pd.pivot_table(data, # 制作透視表的數據
values=None, # 值
index=None, # 行索引
columns=None, # 列屬性
aggfunc='mean', # 使用的函數,默認是均值
fill_value=None, # 缺失值填充
margins=False, # 是否顯示總計
dropna=True, # 缺失值處理
margins_name='All', # 總計顯示為All
observed=False,
sort=True # 排序功能
)

1.1第一個示例通過求和聚合值
df = pd.DataFrame({"A": ["foo", "foo", "foo", "foo", "foo",
"bar", "bar", "bar", "bar"],
"B": ["one", "one", "one", "two", "two",
"one", "one", "two", "two"],
"C": ["small", "large", "large", "small",
"small", "large", "small", "small",
"large"],
"D": [1, 2, 2, 3, 3, 4, 5, 6, 7],
"E": [2, 4, 5, 5, 6, 6, 8, 9, 9]})

import numpy as np
table = pd.pivot_table(df, values='D', index=['A', 'B'],
columns=['C'], aggfunc=np.sum)
table

1.2可以使用fill_value參數來填充缺失的值。
table = pd.pivot_table(df, values='D', index=['A', 'B'],
columns=['C'], aggfunc=np.sum, fill_value=0)
table

1.3下一個示例通過計算多個列的平均值進行聚合。
table = pd.pivot_table(df, values=['D', 'E'], index=['A', 'C'],
aggfunc={'D': np.mean,
'E': np.mean})
table

1.4計算任意給定值列的多種聚合類型。
table = pd.pivot_table(df, values=['D', 'E'], index=['A', 'C'],
aggfunc={'D': np.mean,
'E': [min, max, np.mean]})
table

2.cross_tab
計算兩個(或更多)因子的簡單交叉表。默認情況下,除非傳遞值數組和聚合函數,否則計算因子的頻率表。
pandas.crosstab(index, # 行索引,必須是數組結構數據,或者Series,或者是二者的列表形式
columns, # 列字段;數據要求同上
values=None, # 待透視的數據
rownames=None, # 行列名字
colnames=None,
aggfunc=None, # 透視的函數
margins=False, # 匯總及名稱設置
margins_name='All',
dropna=True, # 舍棄缺失值
normalize=False # 數據歸一化;可以是布爾值、all、index、columns、或者{0,1}
)
2.1示例
import pandas as pd
df = pd.DataFrame(columns=['date','type','value'])
df['date'] = ['2022-1-{}'.format(i+1) for i in range(3)]*2
df['date'] = pd.to_datetime(df.date)
df['type'] = list('abcaac')
df.value = [2022,1,20,11,11,9]
df

cross_tab = pd.crosstab(index=df.date,columns=df.type,values=df.value,aggfunc='mean')
cross_tab

3.gropyby
df.groupby(['date','type'])['value'].mean().unstack()

4.melt
這個函數很有用,可以將DataFrame轉換為一種格式,其中一列或多列是標識符變量(id_vars),而所有其他列,被認為是測量變量(value_vars),被“unpivot”到行軸,只留下兩個非標識符列,‘variable’和‘value’。
pandas.melt(frame,
id_vars=None,
value_vars=None,
var_name=None,
value_name='value',
ignore_index=True,
col_level=None)
- frame:要處理的數據框DataFrame。
- id_vars:表示不需要被轉換的列名
- value_vars:表示需要轉換的列名,如果剩下的列全部都需要進行轉換,則不必寫
- var_name和value_name:自定義設置對應的列名,相當於是取新的列名
- igonore_index:是否忽略原列名,默認是True,就是忽略了原索引名,重新生成0,1,2,3,4....的自然索引
- col_level:如果列是多層索引列MultiIndex,則使用此參數;這個參數少用
df3 = pd.melt(df,id_vars='date',value_vars=['type','value'],value_name='observation')
df3

5.wide_to_long
寬面板到長格式。不太靈活,但比melt更方便用戶。
使用 stubnames [‘ a’,‘ b’] ,這個函數期望找到一組或多組格式為 A-suffix1,A-suffix2,... ,B-suffix1,b-suffix2的列,... 您可以使用 j 在結果的長格式中指定要調用這個后綴的內容(例如 j =’year’)
假定這些寬變量的每一行都由 i 惟一標識(可以是單個列名或列名列表)
數據框架中的所有其余變量都保持不變。
wide_to_long(
df,
stubnames,
i,
j,
sep: str = "",
suffix: str = "\\d+"
- df:待轉換的數據框
- stubnames:寬表中列名相同的存根部分
- i:要用作 id 變量的列
- j:給長格式的“后綴”列設置 columns
- sep:設置要刪除的分隔符。例如 columns 為 A-2020,則指定 sep='-' 來刪除分隔符。默認為空。
- suffix:通過設置正則表達式取得“后綴”。默認'\d+'表示取得數字后綴。沒有數字的“后綴”可以用'\D+'來取得
5.1example
np.random.seed(123)
df = pd.DataFrame({"A1970" : {0 : "a", 1 : "b", 2 : "c"},
"A1980" : {0 : "d", 1 : "e", 2 : "f"},
"B1970" : {0 : 2.5, 1 : 1.2, 2 : .7},
"B1980" : {0 : 3.2, 1 : 1.3, 2 : .1},
"X" : dict(zip(range(3), np.random.randn(3)))
})
df

df['id'] = df.index
pd.wide_to_long(df, ["A", "B"], i='id', j="year")

5.2也可以有非整數作為后綴。
df = pd.DataFrame({
'famid': [1, 1, 1, 2, 2, 2, 3, 3, 3],
'birth': [1, 2, 3, 1, 2, 3, 1, 2, 3],
'ht_one': [2.8, 2.9, 2.2, 2, 1.8, 1.9, 2.2, 2.3, 2.1],
'ht_two': [3.4, 3.8, 2.9, 3.2, 2.8, 2.4, 3.3, 3.4, 2.9]
})
df

l = pd.wide_to_long(df, stubnames='ht', i=['famid', 'birth'], j='age',
sep='_', suffix=r'\w+')
l

6.explode
explode(column, ignore_index=False)
- column:待爆炸的元素
- ignore_index:是否忽略索引;默認是False,保持原來的索引
df = pd.DataFrame({'A': [[0, 1, 2], 'foo', [], [3, 4]],
'B': 1,
'C': [['a', 'b', 'c'], np.nan, [], ['d', 'e']]})
df

df.explode(list('AC'))

6.1小技巧(將字符串轉換為列表)
df = pd.DataFrame(columns=['name','hobbies'])
df.name = ['peanut','憨憨']
df.hobbies = ['badminton,study','badminton,research']
df

df['hobbies'] = df['hobbies'].apply(lambda x: x.split(','))
df

df.explode('hobbies')

7.transform
df = pd.DataFrame({'A' : ['foo', 'bar', 'foo', 'bar',
'foo', 'bar'],
'B' : ['one', 'one', 'two', 'three',
'two', 'two'],
'C' : [1, 5, 5, 2, 5, 5],
'D' : [2.0, 5., 8., 1., 2., 9.]})

df.groupby('A')['C','D'].transform(lambda x: sum(x))

