1. 程式人生 > 實用技巧 >pandas之表的長寬轉換

pandas之表的長寬轉換

表格的長寬轉換

表格長寬轉換也是一種透視表操作

  • df.pivot()
    • 將 一張長表 轉為 多張寬表
  • pd.melt()
    • 將 多張寬表 轉為 一張長表

二者互為逆操作


pivot和pivot_table的區別

  • pivot轉換後,如果表索引有重複值會直接出錯
  • pivot_table轉換後,如果表索引有重複值會聚合為一個輸出,不會出錯
    • 如果資料不重複,pivot_table得到的結果和pivot一致
    • pivot_table更常用
df_test = pd.DataFrame({
    'foo': ['one','one','one','two','two','two'],
    'bar': ['A', 'B', 'C', 'A', 'B', 'C'],
    'baz': [1, 2, 3, 4, 5, 6]
})
df_test.pivot(index='foo', columns='bar', values='baz')  # 不帶聚合
df_test.pivot_table(index='foo', columns='bar', values='baz')  # 帶聚合,推薦

df_test = pd.DataFrame({
    'foo': ['one','one','one','one','two','two'],
    'bar': ['A', 'B', 'C', 'A', 'B', 'C'],
    'baz': [1, 2, 3, 4, 5, 6]
})
df_test.pivot_table(index='foo', columns='bar', values='baz')
# df_test.pivot(index='foo', columns='bar', values='baz')  # 不帶聚合,重複即出錯(長寬表格轉換)
總結:
重複指index,columns一致



將“長格式”旋轉為“寬格式”:pivot()
將一列拆分為多列

1列值做行索引
1列值做列索引
剩下的值做表格值
多個時間序列資料通常是以所謂的“長格式”(long)或“堆疊格式”(stacked)儲存在資料庫和CSV中的
ldata = pd.read_csv('examples/pivot.csv', parse_dates=['date'])
ldata[:14]  # 1年,4個季度,3個指標,共12條資料
date	item	value	value2
0	1959-03-31	realgdp	2710.349	-0.492362
1	1959-03-31	infl	0.000	0.938709
2	1959-03-31	unemp	5.800	-1.249725
3	1959-06-30	realgdp	2778.801	-1.299523
4	1959-06-30	infl	2.340	-0.601390
5	1959-06-30	unemp	5.100	0.958452
6	1959-09-30	realgdp	2775.488	-1.239327
7	1959-09-30	infl	2.740	0.908910

# pivot()前兩個引數是行和列索引,最後一個可選引數是需要拆分的列
ldata.pivot('date', 'item', 'value').head()
# 如果不加第三個引數,就會分拆除行、列索引外的所有列,大概率返回3維dataframe
ldata.pivot('date', 'item').head()
ldata.pivot('date', 'item')['value'].head()  # 同上


用分組聚合(groupby)和重塑(unstack)一般可以實現所有資料重塑功能
不使用新學的pivot方法,
將1天變成一行,item類別從1列變成3列
# 先把要選擇的列變為行索引 兩種方式
# 1 分組聚合重塑,min()用來保留原值的
ldata.groupby(['date', 'item'])['value'].min().unstack().head()  # 這裡聚合運算返回的直接是原值
# 方法2,類似分組聚合
ldata.groupby(['date', 'item']).min().head()  # 分組聚合的方式
ldata.set_index(['date', 'item']).head()  # 將這兩列轉為行索引,效果同上
ldata.set_index(['date', 'item']).unstack()['value'].head()

將“寬格式”旋轉為“長格式”

將多列合併為1列

pivot的逆運算是pandas.melt

它不是將一列轉換到多個新的DataFrame,而是合併多個列成為一個,產生一個比輸入長的DataFrame

df2 = pd.DataFrame({'key': ['foo', 'bar', 'baz'], 'A': [1, 2, 3], 'B': [4, 5, 6], 'C': [7, 8, 9]})
# 可看性不好
dfx = pd.melt(df2)  # 將無論多少列轉為2列,1列是原列索引,1列是原值

當使用pandas.melt,最好指明哪些列是分組指標
指定key列是唯一分組指標,其它列是資料值
melted = pd.melt(df2, ['key'])
xxx = melted.pivot('key', 'variable', 'value').reset_index()  # reset_index()將行索引轉為普通列,set_index()普通列轉為行索引
xxx.columns.name = ''  # 去除列索引name

# 還可以指定哪些列參與合併
pd.melt(df2, ['key'])
pd.melt(df2, ['key'], value_vars=['A', 'B'])  # 沒有c

pandas.melt可以不用分組指標
pd.melt(df2, value_vars=['A', 'B'])

綜合練習:同時指定多個分組指標,和參與列
pd.melt(df2, ['key','A'])  # 指定多個分組指標
pd.melt(df2, ['key','A'], value_vars=['B'])  # 指定多個分組指標和參與列