【问题标题】:python pandas melt on combined columnspython pandas在组合列上融化
【发布时间】:2018-07-25 18:25:26
【问题描述】:

我有一个这样的数据框。我有常规字段直到“状态”然后我将有拖车(3 列 tr1* 代表 1 个拖车)我想将这些拖车转换为行。我尝试了融化功能,但我只能使用 1 个拖车柱。请看下面的例子你就明白了

Name number city       state    tr1num   tr1acct   tr1ct  tr2num  tr2acct   tr2ct   tr3num   tr3acct  tr3ct 
DJ   10     Edison     nj       1001     20345     Dew    1002    20346     Newca.  1003.    20347.   pen 
ND   20     Newark     DE       2001     1985      flor   2002    1986      rodge

我期待这样的输出。

Name number city       state    trnum   tracct     trct
DJ   10     Edison     nj       1001     20345     Dew   
DJ   10     Edison     nj       1002     20346     Newca
DJ   10     Edison     nj       1003     20347     pen
ND   20     Newark     DE       2001     1985      flor
ND   20     Newark     DE       2002     1986      rodge

【问题讨论】:

    标签: pandas melt


    【解决方案1】:

    你需要看看使用pd.wide_to_long。但是,您需要先进行一些列重命名。

    df = df.set_index(['Name','number','city','state'])
    df.columns = df.columns.str.replace('(\D+)(\d+)(\D+)',r'\1\3_\2')
    df = df.reset_index()
    
    pd.wide_to_long(df, ['trnum','trct','tracct'], 
                    ['Name','number','city','state'], 'Code',sep='_',suffix='\d+')\
      .reset_index()\
      .drop('Code',axis=1)
    

    输出:

      Name  number    city state   trnum    trct   tracct
    0   DJ      10  Edison    nj  1001.0     Dew  20345.0
    1   DJ      10  Edison    nj  1002.0  Newca.  20346.0
    2   DJ      10  Edison    nj  1003.0     pen  20347.0
    3   ND      20  Newark    DE  2001.0    flor   1985.0
    4   ND      20  Newark    DE  2002.0   rodge   1986.0
    5   ND      20  Newark    DE     NaN     NaN      NaN
    

    【讨论】:

    • 非常感谢。我在常规列中也有整数,例如 buw1no。我只举了一个小例子,但我有大约 50 列和 500k 行 1 运行
    • @NDommeti pd.wide_to_long 是要使用的方法,否则您最终会进行多次融合并将数据帧连接在一起。使用 pd.wide_to_long,您必须使列标题以“stub_number”格式保持一致。祝你好运。
    • 真棒..会做到的..感谢@Scott Boston 的指导。如果我必须使用 pyspark,我应该使用什么方法。
    • @NDommeti 我对 pyspark 不够熟悉。
    【解决方案2】:

    您可以通过重命名列和位并应用 pandas wide_to_long 方法来实现此目的。下面是产生所需输出的代码。

    df = pd.DataFrame({"Name":["DJ", "ND"], "number":[10,20], "city":["Edison", "Newark"], "state":["nj","DE"],
                      "trnum_1":[1001,2001], "tracct_1":[20345,1985], "trct_1":["Dew", "flor"], "trnum_2":[1002,2002],
                      "trct_2":["Newca", "rodge"], "trnum_3":[1003,None], "tracct_3":[20347,None], "trct_3":["pen", None]})
    
    pd.wide_to_long(df, stubnames=['trnum', 'tracct', 'trct'], i='Name', j='dropme', sep='_').reset_index().drop('dropme', axis=1)\
      .sort_values('trnum')
    

    输出

      Name state city number trnum  tracct  trct
    0   DJ  nj  Edison  10  1001.0  20345.0 Dew
    1   DJ  nj  Edison  10  1002.0  NaN     Newca
    2   DJ  nj  Edison  10  1003.0  20347.0 pen
    3   ND  DE  Newark  20  2001.0  1985.0  flor
    4   ND  DE  Newark  20  2002.0  NaN    rodge
    5   ND  DE  Newark  20  NaN     NaN   None
    

    【讨论】:

    • 非常感谢。因为我有数百万行,所以我无法根据实际数据定义列。我会研究wide_to_long
    【解决方案3】:

    另一种选择:

    df = pd.DataFrame({'col1': [1,2,3], 'col2':[3,4,5], 'col3':[5,6,7], 'tr1':[0,9,8], 'tr2':[0,9,8]})
    

    df:

     col1   col2    col3    tr1 tr2
        0   1   3   5   0   0
        1   2   4   6   9   9
        2   3   5   7   8   8
    

    创建 2 个 df 的子集:

    tr1_df = df[['col1', 'col2', 'col3', 'tr1']].rename(index=str, columns={"tr1":"tr"})
    tr2_df = df[['col1', 'col2', 'col3', 'tr2']].rename(index=str, columns={"tr2":"tr"})
    res = pd.concat([tr1_df, tr2_df])
    

    结果:

    col1 col2   col3    tr
    0   1   3   5   0
    1   2   4   6   9
    2   3   5   7   8
    0   1   3   5   0
    1   2   4   6   9
    2   3   5   7   8
    

    【讨论】:

      【解决方案4】:

      一个选项是来自pyjanitorpivot_longer 函数,使用.value 占位符:

      # pip install git+https://github.com/pyjanitor-devs/pyjanitor.git
      import janitor 
      import pandas as pd
      
      (df
      .pivot_longer(
            index=slice("Name", "state"),
            names_to=(".value", ".value"),
            names_pattern=r"(.+)\d(.+)",
            sort_by_appearance=True)
      .dropna()
      )
      
        Name  number    city state   trnum   tracct    trct
      0   DJ      10  Edison    nj  1001.0  20345.0     Dew
      1   DJ      10  Edison    nj  1002.0  20346.0  Newca.
      2   DJ      10  Edison    nj  1003.0  20347.0     pen
      3   ND      20  Newark    DE  2001.0   1985.0    flor
      4   ND      20  Newark    DE  2002.0   1986.0   rodge
      

      .value 将与其关联的列部分保留为标题,并且由于我们有多个.value,因此将它们组合成一个单词。 .value 由 names_pattern 中的组确定,这是一个正则表达式。

      请注意,目前在 dev 中可以使用多个 .value 选项。

      【讨论】:

        猜你喜欢
        • 2018-02-27
        • 2020-04-18
        • 2016-05-13
        • 2018-01-22
        • 2014-04-03
        • 1970-01-01
        • 2019-10-20
        • 1970-01-01
        • 2016-12-16
        相关资源
        最近更新 更多