如何在Python中{透视|反规范化|操纵} CSV表

时间:2018-06-27 17:16:34

标签: python pandas dataframe

对不起,标题太乱了,我不知道该如何措辞好。

假设我有一个表,其中前三列是foo bar和baz。然后是一些任意列。我想对表进行操作,以使这些任意列都折叠在名为num的列下。

一个例子使这一点更清楚

foo, bar, baz, 100, 101, 102, 103, 104,
1,   1,   1,  10,  11,  12,  13,  14,
1,   1,   2,  15,  16,  17,  18,  19,
1,   2,   1,  20,  21,  22,  23,  24,

此输入应转置为:

num, foo, bar, baz, value,
100,   1,    1,  1,    10,
100,   1,    1,  2,    15,
100,   1,    2,  1,    20,
101,   1,    1,  1,    11,
101,   1,    1,  2,    16,
101,   1,    2,  1,    21,
102,   1,    1,  1,    12,
102,   1,    1,  2,    17,
102,   1,    2,  1,    22,
...

我写了一个自定义的Python解决方案来做到这一点。并不困难,但是我觉得这是在重新发明轮子。

是否有一种方法可以通过类似pandas之类的库或其他一些表操作模块来实现?

4 个答案:

答案 0 :(得分:6)

使用pandas.melt

res = pd.melt(df, id_vars=['foo', 'bar', 'baz'])

print(res)

    foo  bar  baz variable  value
0     1    1    1      100     10
1     1    1    2      100     15
2     1    2    1      100     20
3     1    1    1      101     11
4     1    1    2      101     16
5     1    2    1      101     21
6     1    1    1      102     12
7     1    1    2      102     17
8     1    2    1      102     22
9     1    1    1      103     13
10    1    1    2      103     18
11    1    2    1      103     23
12    1    1    1      104     14
13    1    1    2      104     19
14    1    2    1      104     24

答案 1 :(得分:2)

cols = np.concatenate([['num'], df.columns[:3], ['value']])
pd.DataFrame([
    [a, b, c, d, e]
    for b, c, d, *x in df.values
    for a, e in zip(df.columns[3:], x)
]).set_axis(cols, axis=1, inplace=False).sort_values('num')

    num  foo  bar  baz  value
0   100    1    1    1     10
5   100    1    1    2     15
10  100    1    2    1     20
1   101    1    1    1     11
6   101    1    1    2     16
11  101    1    2    1     21
2   102    1    1    1     12
7   102    1    1    2     17
12  102    1    2    1     22
3   103    1    1    1     13
8   103    1    1    2     18
13  103    1    2    1     23
4   104    1    1    1     14
9   104    1    1    2     19
14  104    1    2    1     24

答案 2 :(得分:2)

您可以对set_indexstack和某些列重命名使用数据帧重塑:

(df.set_index(['foo','bar','baz'])
   .stack()
   .reset_index(name='value')
   .rename(columns={'level_3':'num'}))

输出:

    foo  bar  baz  num  value
0     1    1    1  100     10
1     1    1    1  101     11
2     1    1    1  102     12
3     1    1    1  103     13
4     1    1    1  104     14
5     1    1    2  100     15
6     1    1    2  101     16
7     1    1    2  102     17
8     1    1    2  103     18
9     1    1    2  104     19
10    1    2    1  100     20
11    1    2    1  101     21
12    1    2    1  102     22
13    1    2    1  103     23
14    1    2    1  104     24

答案 3 :(得分:0)

如上所述,pandas.melt是最好的方法!

import pandas as pd
import numpy as np

#Create the dataframe
df = pd.DataFrame({'foo' : np.random.randint(low = 0, high=5, size = 3), 'bar' : 
                  np.random.randint(low = 0, high=5, size = 3),'baz' : 
                  np.random.randint(low = 0, high=5, size = 3)})

for i in range(100,105):
df['%d'%i] = np.random.randint(low = 10, high=20, size = 3)

print(df) 
   foo  bar  baz  100  101  102  103  104
0    2    1    4   16   14   13   16   11
1    3    0    4   11   17   12   15   18
2    4    1    1   13   15   11   18   17

现在,主要功能是:

pd.melt(frame=df, id_vars= ['foo', 'bar', 'baz'], value_vars= ['%d'%i for i in 
range(100,105)])

#output
   foo  bar baz variable  value
0   2   1   4   100        16
1   3   0   4   100        11
2   4   1   1   100        13
3   2   1   4   101        14
4   3   0   4   101        17
5   4   1   1   101        15
6   2   1   4   102        13
7   3   0   4   102        12
8   4   1   1   102        11
9   2   1   4   103        16
10  3   0   4   103        15
11  4   1   1   103        18
12  2   1   4   104        11
13  3   0   4   104        18
14  4   1   1   104        17