簡體   English   中英

按 N 列的塊重塑 Pandas dataframe 列

[英]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_bb_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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM