【问题标题】:How to reshape dataframe, wide to long, for several variables in one or several calls?如何在一次或多次调用中为多个变量重塑数据框,从宽到长?
【发布时间】:2019-05-04 05:57:08
【问题描述】:

我无法将以下数据框改造成长格式:

  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

【问题讨论】:

  • 请查看多索引数据帧和堆栈取消堆栈命令。如果您无法弄清楚,请告诉我,我会给您详细的答复。

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


【解决方案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

【讨论】:

  • 谢谢我让我了解wide_to_long 上面也很有帮助
  • 我从未想过在列名中交换单词以使用wide_to_long :) +1
【解决方案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

【讨论】:

    【解决方案3】:

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

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

    您可以使用pyjanitor 中的pivot_longer 函数:

    import re
     # pip install janitor
     # you could also install latest dev version
     # pip install git+https://github.com/pyjanitor-devs/pyjanitor.git
    
    import janitor
    import pandas as pd
    (
        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
    

    如果您确定您的数据顺序是一致的(t1, t1_pct, t1_valid, t2, t2_pct, ...),您可以使用该顺序通过正则表达式重塑数据:

    df.pivot_longer(index = 'id', 
                    names_to = ['value', 'pct', 'valid'], 
                    names_pattern = ['t\d$', '.*_(pct)$', '.*_(valid)$'])
    
                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
    

    【讨论】:

      猜你喜欢
      • 2020-07-12
      • 1970-01-01
      • 2018-02-17
      • 2021-10-23
      • 2016-05-25
      • 2017-10-13
      • 1970-01-01
      • 1970-01-01
      • 2017-08-08
      相关资源
      最近更新 更多