[英]Reshape Pandas dataframe columns by block of N columns
我有 1 dataframe 需要將列塊重新整形為行。 我嘗試使用 stack() 和 melt() 但無法找到正確的方法。
這是我期望的一個例子:
data = {'id':['a1', 'a2', 'a3', 'a4'],
'year':[20, 20, 19, 18],
'b_A': [1, 2, 3, 4],
'b_B': [5, 6, 7, 8],
'b_C': [9, 10, 11, 12],
'c_A': [13, 14, 15, 16],
'c_B': [17, 18, 19, 20],
'c_C': [21, 22, 23, 24],
'd_A': [25, 26, 27, 28],
'd_B': [29, 30, 31, 32],
'd_C': [33, 34, 35, 36],
}
df = pd.DataFrame(data)
id year b_A b_B b_C c_A c_B c_C d_A d_B d_C
0 a1 20 1 5 9 13 17 21 25 29 33
1 a2 20 2 6 10 14 18 22 26 30 34
2 a3 19 3 7 11 15 19 23 27 31 35
3 a4 18 4 8 12 16 20 24 28 32 36
預期的結果應該是:
id year origin A B C
0 a1 20 b 1 5 9
1 a1 20 c 13 17 21
2 a1 20 d 25 29 33
3 a2 20 b 2 6 10
4 a2 20 c 14 18 22
5 a2 20 d 26 30 34
6 a3 19 b 3 7 11
7 a3 19 c 15 19 23
8 a3 19 d 27 31 35
9 a4 18 b 4 8 12
10 a4 18 c 16 20 24
11 a4 18 d 28 32 36
感謝您的時間和幫助。
您可以通過 DataFrame.set_index 將帶有_
的非列名稱轉換為索引,然后通過DataFrame.set_index
拆分列並通過Series.str.split
DataFrame.stack
:
df1 = df.set_index(['id','year'])
df1.columns = df1.columns.str.split('_', expand=True)
df1 = df1.stack(level=0).reset_index()
print (df1)
id year level_2 A B C
0 a1 20 b 1 5 9
1 a1 20 c 13 17 21
2 a1 20 d 25 29 33
3 a2 20 b 2 6 10
4 a2 20 c 14 18 22
5 a2 20 d 26 30 34
6 a3 19 b 3 7 11
7 a3 19 c 15 19 23
8 a3 19 d 27 31 35
9 a4 18 b 4 8 12
10 a4 18 c 16 20 24
11 a4 18 d 28 32 36
如果需要還可以設置列origin
,可以使用DataFrame.rename_axis
:
df1 = df.set_index(['id','year'])
df1.columns = df1.columns.str.split('_', expand=True)
df1 = df1.rename_axis(['origin',None], axis=1).stack(0).reset_index()
print (df1)
id year origin A B C
0 a1 20 b 1 5 9
1 a1 20 c 13 17 21
2 a1 20 d 25 29 33
3 a2 20 b 2 6 10
4 a2 20 c 14 18 22
5 a2 20 d 26 30 34
6 a3 19 b 3 7 11
7 a3 19 c 15 19 23
8 a3 19 d 27 31 35
9 a4 18 b 4 8 12
10 a4 18 c 16 20 24
11 a4 18 d 28 32 36
或者使用wide_to_long
來改變_
的值順序,比如A_b
到b_A
:
df.columns = [f'{"_".join(x[::-1])}' for x in df.columns.str.split('_')]
df1 = pd.wide_to_long(df,
stubnames=['A','B','C'],
i=['id','year'],
j='origin',
sep='_',
suffix=r'\w+').reset_index()
print (df1)
id year origin A B C
0 a1 20 b 1 5 9
1 a1 20 c 13 17 21
2 a1 20 d 25 29 33
3 a2 20 b 2 6 10
4 a2 20 c 14 18 22
5 a2 20 d 26 30 34
6 a3 19 b 3 7 11
7 a3 19 c 15 19 23
8 a3 19 d 27 31 35
9 a4 18 b 4 8 12
10 a4 18 c 16 20 24
11 a4 18 d 28 32 36
您還可以使用pyjanitor的 pivot_longer function ; 目前您必須從github安裝最新的開發版本:
# install latest dev version
# pip install git+https://github.com/ericmjl/pyjanitor.git
import janitor
df.pivot_longer(index=["id", "year"],
names_to=("origin", ".value"),
names_sep="_")
id year origin A B C
0 a1 20 b 1 5 9
1 a2 20 b 2 6 10
2 a3 19 b 3 7 11
3 a4 18 b 4 8 12
4 a1 20 c 13 17 21
5 a2 20 c 14 18 22
6 a3 19 c 15 19 23
7 a4 18 c 16 20 24
8 a1 20 d 25 29 33
9 a2 20 d 26 30 34
10 a3 19 d 27 31 35
11 a4 18 d 28 32 36
names_sep
值拆分列; 與.value
配對的拆分值保留為列標題,而其他值集中在origin
列下方。
如果您希望數據按出現順序排列,可以使用sort_by_appearance
參數:
df.pivot_longer(
index=["id", "year"],
names_to=("origin", ".value"),
names_sep="_",
sort_by_appearance=True,
)
id year origin A B C
0 a1 20 b 1 5 9
1 a1 20 c 13 17 21
2 a1 20 d 25 29 33
3 a2 20 b 2 6 10
4 a2 20 c 14 18 22
5 a2 20 d 26 30 34
6 a3 19 b 3 7 11
7 a3 19 c 15 19 23
8 a3 19 d 27 31 35
9 a4 18 b 4 8 12
10 a4 18 c 16 20 24
11 a4 18 d 28 32 36
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.