如何使用 Python 将 CSV 数据从宽格式转置为长数据集

How to transpose CSV data from a wide format to long dataset using Python

我需要使用 Python 对任意数量的 "items" 执行以下数据转换。前两列始终相同,然后可能有数千个 "itemN" 列,我希望所有实数值都在一个新的单列中。

我曾尝试使用 pandas.wide_to_long,但据我所知,我会将新名称放入转置的 table 中,如果项目数量可能发生变化,这将不起作用。

type   rid          item1 item2 item3
apple  [81]          1.1   1.1   1.1 
orange [82]          2.2   2.2   2.2 
banana [41,42,43,52] 3.3   3.3   3.3 
kiwi   [90,95]       4.4   4.4   4.4 

type   rid             gid   value
apple  [81]           item1   1.1 
apple  [81]           item2   1.1 
apple  [81]           item3   1.1 
orange [82]           item1   2.2 
orange [82]           item2   2.2 
orange [82]           item3   2.2 
banana [41,42,43,52]  item1   3.3 
banana [41,42,43,52]  item2   3.3 
banana [41,42,43,52]  item3   3.3 
kiwi   [90,95]        item1   4.4 
kiwi   [90,95]        item2   4.4 
kiwi   [90,95]        item3   4.4

到目前为止,我已经尝试过对 numpy 数组使用双 for 循环和索引切片并使用 pandas.wide_to_long。

a = np.array([['apple'  ,tuple([81]) ,1.1 ,1.1 ,1.1] ,['orange' ,tuple([82]) ,2.2 ,2.2 ,2.2],['banana' ,tuple([41,42,43,52]) ,3.3 ,3.3 ,3.3],['kiwi' ,tuple([90,95]) ,4.4 ,4.4 ,4.4]])
names = ['type' ,'rid' ,'item1' ,'item2' ,'item3']
df = pd.DataFrame(a,columns=names)

这看起来像是 DataFrame.explode (pandas 0.25+) 的工作。

# Build a DataFrame identical to the first example data you provided
d = {'type': {0: 'apple', 1: 'orange', 2: 'banana', 3: 'kiwi'},
     'rid': {0: [81], 1: [82], 2: [41, 42, 43, 52], 3: [90, 95]},
     'item1': {0: 1.1, 1: 2.2, 2: 3.3, 3: 4.4},
     'item2': {0: 1.1, 1: 2.2, 2: 3.3, 3: 4.4},
     'item3': {0: 1.1, 1: 2.2, 2: 3.3, 3: 4.4}})
df = pd.DataFrame(d)

# Explode the 'rid' column and reset to default integer index
df.explode('rid').reset_index(drop=True)

     type rid  item1  item2  item3
0   apple  81    1.1    1.1    1.1
1  orange  82    2.2    2.2    2.2
2  banana  41    3.3    3.3    3.3
3  banana  42    3.3    3.3    3.3
4  banana  43    3.3    3.3    3.3
5  banana  52    3.3    3.3    3.3
6    kiwi  90    4.4    4.4    4.4
7    kiwi  95    4.4    4.4    4.4

您可以将前 2 列放入索引,堆叠生成的数据框,然后重置索引:

df.set_index(['type', 'rid']).stack().reset_index()

给出:

      type            rid level_2    0
0    apple           [81]   item1  1.1
1    apple           [81]   item2  1.1
2    apple           [81]   item3  1.1
3   orange           [82]   item1  2.2
4   orange           [82]   item2  2.2
5   orange           [82]   item3  2.2
6   banana  [41,42,43,52]   item1  3.3
7   banana  [41,42,43,52]   item2  3.3
8   banana  [41,42,43,52]   item3  3.3
9     kiwi        [90,95]   item1  4.4
10    kiwi        [90,95]   item2  4.4
11    kiwi        [90,95]   item3  4.4

只需重命名新列即可:

df.set_index(['type', 'rid']).stack().reset_index().rename(columns={'level_2': 'gid',
                                   0: 'value'})

给出预期的数据帧。

简单的答案就是使用 pandas.melt() 函数。

df = df.melt(id_vars=['type', 'rid'], value_vars=['item1', 'item2', 'item3'])

输出: