Python 熊猫从长到宽重塑,通过两个变量

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/22798934/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 01:43:01  来源:igfitidea点击:

Pandas long to wide reshape, by two variables

pythonpandasreshape

提问by Luke

I have data in long format and am trying to reshape to wide, but there doesn't seem to be a straightforward way to do this using melt/stack/unstack:

我有长格式的数据,并且正在尝试将数据重塑为宽格式,但似乎没有使用melt/stack/unstack 的直接方法来做到这一点:

Salesman  Height   product      price
  Knut      6        bat          5
  Knut      6        ball         1
  Knut      6        wand         3
  Steve     5        pen          2

Becomes:

变成:

Salesman  Height    product_1  price_1  product_2 price_2 product_3 price_3  
  Knut      6        bat          5       ball      1        wand      3
  Steve     5        pen          2        NA       NA        NA       NA

I think Stata can do something like this with the reshape command.

我认为 Stata 可以用 reshape 命令做这样的事情。

采纳答案by Karl D.

A simple pivot might be sufficient for your needs but this is what I did to reproduce your desired output:

一个简单的枢轴可能足以满足您的需求,但这是我为重现您想要的输出所做的:

df['idx'] = df.groupby('Salesman').cumcount()

Just adding a within group counter/index will get you most of the way there but the column labels will not be as you desired:

只需添加组内计数器/索引即可完成大部分工作,但列标签不会如您所愿:

print df.pivot(index='Salesman',columns='idx')[['product','price']]

        product              price        
idx            0     1     2      0   1   2
Salesman                                   
Knut         bat  ball  wand      5   1   3
Steve        pen   NaN   NaN      2 NaN NaN

To get closer to your desired output I added the following:

为了更接近您想要的输出,我添加了以下内容:

df['prod_idx'] = 'product_' + df.idx.astype(str)
df['prc_idx'] = 'price_' + df.idx.astype(str)

product = df.pivot(index='Salesman',columns='prod_idx',values='product')
prc = df.pivot(index='Salesman',columns='prc_idx',values='price')

reshape = pd.concat([product,prc],axis=1)
reshape['Height'] = df.set_index('Salesman')['Height'].drop_duplicates()
print reshape

         product_0 product_1 product_2  price_0  price_1  price_2  Height
Salesman                                                                 
Knut           bat      ball      wand        5        1        3       6
Steve          pen       NaN       NaN        2      NaN      NaN       5

Edit: if you want to generalize the procedure to more variables I think you could do something like the following (although it might not be efficient enough):

编辑:如果您想将该过程推广到更多变量,我认为您可以执行以下操作(尽管它可能不够高效):

df['idx'] = df.groupby('Salesman').cumcount()

tmp = []
for var in ['product','price']:
    df['tmp_idx'] = var + '_' + df.idx.astype(str)
    tmp.append(df.pivot(index='Salesman',columns='tmp_idx',values=var))

reshape = pd.concat(tmp,axis=1)

@Luke said:

I think Stata can do something like this with the reshape command.

@卢克 说:

我认为 Stata 可以用 reshape 命令做这样的事情。

You can but I think you also need a within group counter to get the reshape in stata to get your desired output:

您可以,但我认为您还需要一个组内计数器来在 stata 中进行重塑以获得所需的输出:

     +-------------------------------------------+
     | salesman   idx   height   product   price |
     |-------------------------------------------|
  1. |     Knut     0        6       bat       5 |
  2. |     Knut     1        6      ball       1 |
  3. |     Knut     2        6      wand       3 |
  4. |    Steve     0        5       pen       2 |
     +-------------------------------------------+

If you add idxthen you could do reshape in stata:

如果添加,idx则可以在stata以下位置进行重塑:

reshape wide product price, i(salesman) j(idx)

回答by chucklukowski

pivoted = df.pivot('salesman', 'product', 'price')

pg. 192 Python for Data Analysis

页。192 用于数据分析的 Python

回答by Gecko

A bit old but I will post this for other people.

有点旧,但我会发布给其他人。

What you want can be achieved, but you probably shouldn't want it ;) Pandas supports hierarchical indexes for both rows and columns. In Python 2.7.x ...

你想要的可以实现,但你可能不应该想要它 ;) Pandas 支持行和列的分层索引。在 Python 2.7.x 中...

from StringIO import StringIO

raw = '''Salesman  Height   product      price
  Knut      6        bat          5
  Knut      6        ball         1
  Knut      6        wand         3
  Steve     5        pen          2'''
dff = pd.read_csv(StringIO(raw), sep='\s+')

print dff.set_index(['Salesman', 'Height', 'product']).unstack('product')

Produces a probably more convenient representation than what you were looking for

产生可能比您正在寻找的更方便的表示

                price             
product          ball bat pen wand
Salesman Height                   
Knut     6          1   5 NaN    3
Steve    5        NaN NaN   2  NaN

The advantage of using set_index and unstacking vs a single function as pivot is that you can break the operations down into clear small steps, which simplifies debugging.

使用 set_index 和 unstacking 与使用单个函数作为主元的优势在于,您可以将操作分解为清晰的小步骤,从而简化调试。

回答by Charles Clayton

Here's another solution more fleshed out, taken from Chris Albon's site.

这是另一个更充实的解决方案,取自Chris Albon 的网站

Create "long" dataframe

创建“长”数据框

raw_data = {'patient': [1, 1, 1, 2, 2],
                'obs': [1, 2, 3, 1, 2],
          'treatment': [0, 1, 0, 1, 0],
              'score': [6252, 24243, 2345, 2342, 23525]}

df = pd.DataFrame(raw_data, columns = ['patient', 'obs', 'treatment', 'score'])

Make a "wide" data

制作“宽”数据

df.pivot(index='patient', columns='obs', values='score')

回答by ALollz

Karl D's solution gets at the heart of the problem. But I find it's far easier to pivot everything (with .pivot_tablebecause of the two index columns) and then sortand assign the columns to collapse the MultiIndex:

Karl D 的解决方案是问题的核心。但是我发现旋转所有内容(.pivot_table因为有两个索引列)然后sort分配列以折叠以下内容要容易得多MultiIndex

df['idx'] = df.groupby('Salesman').cumcount()+1
df = df.pivot_table(index=['Salesman', 'Height'], columns='idx', 
                    values=['product', 'price'], aggfunc='first')

df = df.sort_index(axis=1, level=1)
df.columns = [f'{x}_{y}' for x,y in df.columns]
df = df.reset_index()

Output:

输出:

  Salesman  Height  price_1 product_1  price_2 product_2  price_3 product_3
0     Knut       6      5.0       bat      1.0      ball      3.0      wand
1    Steve       5      2.0       pen      NaN       NaN      NaN       NaN