在Pandas中转动每个小组

时间:2015-06-10 13:07:01

标签: python pandas pivot

使用Pandas我已经在我的数据框架上调用了groupby并获得了以下内容:

>>>grouped = df.groupby(['cid'])
for key, gr in grouped:
        print(key)
        print(gr)
Out: cid  price
     121  12
     121  10
     121  9

我想让每个小组像:

一样
cid price1 price2 price3
121     12     10      9

使用Pandas做到这一点的正确方法是什么?

2 个答案:

答案 0 :(得分:4)

假设你的框架看起来像

>>> df = pd.DataFrame({"cid": np.arange(64)//8, "price": np.arange(64)})
>>> df.head()
   cid  price
0    0      0
1    0      1
2    0      2
3    0      3
4    0      4

然后我认为通过合并groupbypivot可以得到你想要的东西:

df = pd.DataFrame({"cid": np.arange(64)//8, "price": np.arange(64)})
df["num"] = df.groupby("cid")["price"].cumcount() + 1
pivoted = df.pivot(index="cid", columns="num", values="price")
pivoted.columns = "price" + pivoted.columns.astype(str)
pivoted = pivoted.reset_index()

给出了

>>> pivoted
   cid  price1  price2  price3  price4  price5  price6  price7  price8
0    0       0       1       2       3       4       5       6       7
1    1       8       9      10      11      12      13      14      15
2    2      16      17      18      19      20      21      22      23
3    3      24      25      26      27      28      29      30      31
4    4      32      33      34      35      36      37      38      39
5    5      40      41      42      43      44      45      46      47
6    6      48      49      50      51      52      53      54      55
7    7      56      57      58      59      60      61      62      63

除此之外:在字符串结尾后粘贴数字,例如" price5",通常不是一个好主意。你不能真正与他们合作,他们不会按照你期望的方式排序等。

首先,我们创建一个列,显示价格中的索引:

>>> df["num"] = df.groupby("cid")["price"].cumcount() + 1
>>> df.head(10)
   cid  price  num
0    0      0    1
1    0      1    2
2    0      2    3
[etc.]
7    0      7    8
8    1      8    1
9    1      9    2

然后我们pivot

>>> pivoted = df.pivot(index="cid", columns="num", values="price")
>>> pivoted
num   1   2   3   4   5   6   7   8
cid                                
0     0   1   2   3   4   5   6   7
1     8   9  10  11  12  13  14  15
2    16  17  18  19  20  21  22  23
3    24  25  26  27  28  29  30  31
4    32  33  34  35  36  37  38  39
5    40  41  42  43  44  45  46  47
6    48  49  50  51  52  53  54  55
7    56  57  58  59  60  61  62  63

然后我们修复了这些列:

>>> pivoted.columns = "price" + pivoted.columns.astype(str)
>>> pivoted
     price1  price2  price3  price4  price5  price6  price7  price8
cid                                                                
0         0       1       2       3       4       5       6       7
1         8       9      10      11      12      13      14      15
2        16      17      18      19      20      21      22      23
3        24      25      26      27      28      29      30      31
4        32      33      34      35      36      37      38      39
5        40      41      42      43      44      45      46      47
6        48      49      50      51      52      53      54      55
7        56      57      58      59      60      61      62      63

最后我们重置索引:

>>> pivoted = pivoted.reset_index()
>>> pivoted
   cid  price1  price2  price3  price4  price5  price6  price7  price8
0    0       0       1       2       3       4       5       6       7
1    1       8       9      10      11      12      13      14      15
2    2      16      17      18      19      20      21      22      23
3    3      24      25      26      27      28      29      30      31
4    4      32      33      34      35      36      37      38      39
5    5      40      41      42      43      44      45      46      47
6    6      48      49      50      51      52      53      54      55
7    7      56      57      58      59      60      61      62      63

答案 1 :(得分:2)

这里使用unstack()快速修改了@ DSM的方法。我将借用@ DSM的示例数据,以便轻松比较pivot()unstack()的结果:

>>> df = pd.DataFrame({"cid": np.arange(64)//8, "price": np.arange(64)})
>>> df['num'] = df.groupby('cid').cumcount()
>>> df.set_index(['cid','num']).unstack()

    price                            
num     0   1   2   3   4   5   6   7
cid                                  
0       0   1   2   3   4   5   6   7
1       8   9  10  11  12  13  14  15
2      16  17  18  19  20  21  22  23
3      24  25  26  27  28  29  30  31
4      32  33  34  35  36  37  38  39
5      40  41  42  43  44  45  46  47
6      48  49  50  51  52  53  54  55
7      56  57  58  59  60  61  62  63