如何为一个或多个调用中的多个变量重塑数据框,从宽到长?

时间:2018-12-02 22:40:09

标签: python-3.x pandas pandas-groupby

我无法将下面的数据框重整为长格式:

  df = pd.DataFrame({'id': [66602088802, 85002620928],
     't1': ['car', 'house'],
     't1_pct': [0.46, 0.51],
     't1_valid': [True, True],
     't2': ['bike', 'car'],
     't2_pct': [0.15, 0.07],
     't2_valid': [True, True],
     't3': ['car', 'toy'],
     't3_pct': [0.06, 0.07],
     't3_valid': [False, False]})

    id               t1     t1_pct  t1_valid t2  t2_pct t2_valid    t3  t3_pct  t3_valid
0   66602088802     car     0.46    True    bike    0.15    True    car     0.06    False
1   85002620928     house   0.51    True    car     0.07    True    toy     0.07    False

我想要的结果如下。我尝试使用pandas.wide_to_long(),但到目前为止还没有运气。预先感谢。

    id         test  value     pct     valid
66602088802    1      car     0.46     True
85002620928    1      house   0.51     True
66602088802    2      bike    0.15     True
85002620928    2      car     0.07     True
66602088802    3      car     0.06     False
85002620928    3      toy     0.07     False

谢谢。

熊猫0.23.4

python 3.7.1

3 个答案:

答案 0 :(得分:2)

我认为wide_to_long不能重塑您所需的形状,您可以使用melt进行检查

s=df.melt('id')
s=pd.concat([s,s.variable.str.split('_',expand=True)],1).fillna('value')
s.set_index(['id',0,1]).value.unstack().reset_index().rename(columns={0:'text'})
1           id text   pct  valid  value
0  66602088802   t1  0.46   True    car
1  66602088802   t2  0.15   True   bike
2  66602088802   t3  0.06  False    car
3  85002620928   t1  0.51   True  house
4  85002620928   t2  0.07   True    car
5  85002620928   t3  0.07  False    toy

答案 1 :(得分:1)

您可以使用wide_to_long;问题只是您的列名需要稍作更改,以便存根名为['pct', 'valid', 'value'],而不是t#

import pandas as pd
import numpy as np

# Reverse order of words around '_'
df.columns = ['_'.join(x.split('_')[::-1]) for x in df.columns]
# Add prefix for other stubs
df = df.rename(columns= dict((f't{i}', f'value_t{i}') for i in np.arange(1,4,1)))

pd.wide_to_long(df, stubnames=['pct', 'valid', 'value'], 
                i='id', j='test', suffix='.*', sep='_').reset_index()

输出:

            id test   pct  valid  value
0  66602088802   t1  0.46   True    car
1  85002620928   t1  0.51   True  house
2  66602088802   t2  0.15   True   bike
3  85002620928   t2  0.07   True    car
4  66602088802   t3  0.06  False    car
5  85002620928   t3  0.07  False    toy

答案 2 :(得分:1)

这是一个老问题;此答案可能对寻找替代方案的新访问者有所帮助。

这个答案借鉴了@ALollz 在重塑前重命名列的解决方案。

您可以使用 pivot_longer 中的 pyjanitor 函数;目前您必须从 github 安装最新的开发版本:

import re

 # install latest dev version
 # pip install git+https://github.com/ericmjl/pyjanitor.git

import janitor
(
    df.rename(columns=lambda column: f"{column}_value" 
                                     if re.match("t\d$", column) 
                                     else column)
      .pivot_longer(index="id", 
                    names_to=("temp", ".value"), 
                    names_sep="_")
      .drop(columns="temp")
)

          id    value   pct     valid
0   66602088802 car     0.46    True
1   85002620928 house   0.51    True
2   66602088802 bike    0.15    True
3   85002620928 car     0.07    True
4   66602088802 car     0.06    False
5   85002620928 toy     0.07    False