【问题标题】:How to melt a dataframe based on a pattern of the column name?如何根据列名的模式融化数据框?
【发布时间】:2022-11-10 23:14:27
【问题描述】:

我正在尝试融化数据框

Year | Baseline_low | Baseline_high | Overall_low | Overall_high
================================================================    
2022 |            1 |             2 |           3 |            4
2023 |            5 |             6 |           7 |            8

对此:

2022 | Baseline |  low | 1
2022 | Baseline | high | 2

_low_high 结尾的列比我列出的要多得多,所以我想使用一种模式来拆分列。

melt 可以做到这一点吗?

我见过这个similar question,但它的结构与我的数据框略有不同。

【问题讨论】:

    标签: pandas


    【解决方案1】:

    如果您的目标是成为纯粹的熊猫,那么是的,melt 是关键:

    import io
    import pandas as pd
    
    df = pd.read_csv(io.StringIO("""Year | Baseline_low | Baseline_high | Overall_low | Overall_high  
    2022 |            1 |             2 |           3 |            4
    2023 |            5 |             6 |           7 |            8"""), sep="|")
    df.columns = [column.strip() for column in df.columns]
    
    final = df.melt(id_vars=["Year"])
    final["Type"] = final["variable"].apply(lambda x: x.split("_")[0])
    final["State"] = final["variable"].apply(lambda x: x.split("_")[1])
    

    然后只需根据列名拆分您需要的信息,它就会返回:

       Year       variable  value      Type State
    0  2022   Baseline_low      1  Baseline   low
    1  2023   Baseline_low      5  Baseline   low
    2  2022  Baseline_high      2  Baseline  high
    3  2023  Baseline_high      6  Baseline  high
    4  2022    Overall_low      3   Overall   low
    5  2023    Overall_low      7   Overall   low
    6  2022   Overall_high      4   Overall  high
    7  2023   Overall_high      8   Overall  high
    

    【讨论】:

      【解决方案2】:
      #melt
      df2=df.melt('Year')
      
      # split the columns
      df2[['col','level']]=df2['variable'].str.split('_', expand=True)
      
      # pivot
      df2.pivot(index=['Year','level'], columns='col', values='value').reset_index().rename_axis(columns=None) 
      
      #rename_axis, thanks to @mozway!
      
      
      
          Year    level   Baseline    Overall
      0   2022    high           2    4
      1   2022    low            1    3
      2   2023    high           6    8
      3   2023    low            5    7
      

      【讨论】:

      • 我打赌你复制/粘贴了你的其他答案:p
      • 它类似,但没有粘贴,复制是的。我正在考虑将此问题标记为重复
      • @mozway,你的问题,如何摆脱 'col' ,它的第一级列索引
      • .rename_axis(columns=None)
      【解决方案3】:

      仅使用 melt 无法实现此目的。您需要后处理或使用 MultiIndex 进行整形。

      然而,对于janitorpivot_longer 来说,这是一个很好的用例:

      import janitor
      
      df.pivot_longer(
          index='Year', 
          names_to=('.value', 'new'), 
          names_sep='_', 
          sort_by_appearance=True
      )
      

      输出:

         Year   new  Baseline  Overall
      0  2022   low         1        3
      1  2022  high         2        4
      2  2023   low         5        7
      3  2023  high         6        8
      

      如果您确实需要将列名的所有子部分翻转为新列,则不需要.value 占位符。只需传入新的列名:

      df.pivot_longer(
           index = 'Year', 
           names_to = ('Type', 'State'), 
           names_sep = '_')
      
         Year      Type State  value
      0  2022  Baseline   low      1
      1  2023  Baseline   low      5
      2  2022  Baseline  high      2
      3  2023  Baseline  high      6
      4  2022   Overall   low      3
      5  2023   Overall   low      7
      6  2022   Overall  high      4
      7  2023   Overall  high      8
      

      【讨论】:

        【解决方案4】:
        i have a normal solution
        
        df1.set_index('Year').stack().reset_index()
            .assign(col1=lambda dd:dd.level_1.map(lambda x:x.split('_')[0]))
            .assign(col2=lambda dd:dd.level_1.map(lambda x:x.split('_')[1]))
            .drop('level_1',axis=1).pipe(print)
        
          Year  0      col1  col2
        0  2022  1  Baseline   low
        1  2022  2  Baseline  high
        2  2022  3   Overall   low
        3  2022  4   Overall  high
        4  2023  5  Baseline   low
        5  2023  6  Baseline  high
        6  2023  7   Overall   low
        7  2023  8   Overall  high
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2021-12-28
          • 2014-08-10
          • 1970-01-01
          • 1970-01-01
          • 2021-10-27
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多