【问题标题】:Pandas: Split columns into multiple columns by two delimitersPandas:通过两个分隔符将列拆分为多列
【发布时间】:2020-03-23 17:46:14
【问题描述】:

我有这样的数据

ID   INFO
1    A=2;B=2;C=5
2    A=3;B=4;C=1
3    A=1;B=3;C=2

我想将 Info 列拆分为

ID   A    B    C
1    2    2    5
2    3    4    1
3    1    3    2

我可以使用一个分隔符来拆分列

df['A'], df['B'], df['C'] = df['INFO'].str.split(';').str

然后由= 再次拆分,但如果我有很多行,尤其是当有很多字段无法事先硬编码时,这似乎效率不高。

非常欢迎任何建议。

【问题讨论】:

标签: python pandas


【解决方案1】:
values = [dict(item.split("=") for item in value.split(";")) for value in df.INFO]
df[['a', 'b', 'c']] = pd.DataFrame(values)

这将为您提供所需的输出:

    ID INFO         a   b   c
    1  a=1;b=2;c=3  1   2   3
    2  a=4;b=5;c=6  4   5   6
    3  a=7;b=8;c=9  7   8   9

说明: 第一行将每个值转换为字典。 例如

x = 'a=1;b=2;c=3' 
dict(item.split("=") for item in x.split(";"))  

结果: {'a': '1', 'b': '2', 'c': '3'}

DataFrame 可以将字典列表作为输入并将其转换为数据帧。

那么您只需将数据框分配给您想要的列:
df[['a', 'b', 'c']] = pd.DataFrame(values)

【讨论】:

    【解决方案2】:

    您可以将命名组与Series.str.extract 一起使用。最后连接'ID'。这假设您总是在一行中有 A=;B=;和 C=。

    pd.concat([df['ID'], 
               df['INFO'].str.extract('A=(?P<A>\d);B=(?P<B>\d);C=(?P<C>\d)')], axis=1)
    
    #   ID  A  B  C
    #0   1  2  2  5
    #1   2  3  4  1
    #2   3  1  3  2
    

    如果您想要一个更灵活的解决方案来处理单行可能是'A=1;C=2' 的情况,那么我们可以在'=' 上拆分';'partitionpivot 最后得到你想要的输出。

    ### Starting Data
    #ID   INFO
    #1    A=2;B=2;C=5
    #2    A=3;B=4;C=1
    #3    A=1;B=3;C=2
    #4    A=1;C=2
    
    (df.set_index('ID')['INFO']
       .str.split(';', expand=True)
       .stack()
       .str.partition('=')
       .reset_index(-1, drop=True)
       .pivot(columns=0, values=2)
    )
    
    #    A    B  C
    #ID           
    #1   2    2  5
    #2   3    4  1
    #3   1    3  2
    #4   1  NaN  2
    

    【讨论】:

      【解决方案3】:

      浏览系列比遍历数据帧的行要快得多。

      所以我会这样做:

      pd.DataFrame([dict([x.split('=') for x in t.split(';')]) for t in df['INFO']], index=df['ID']).reset_index()
      

      它按预期给出:

         ID  A  B  C
      0   1  2  2  5
      1   2  3  4  1
      2   3  1  3  2
      

      它应该比拆分两次数据框列更快。

      【讨论】:

        【解决方案4】:

        另一种解决方案是Series.str.findAll提取值,然后apply(pd.Series)

        df[["A", "B", "C"]] = df.INFO.str.findall(r'=(\d+)').apply(pd.Series)
        df = df.drop("INFO", 1)
        

        详情:

        df = pd.DataFrame([[1, "A=2;B=2;C=5"],
                        [2, "A=3;B=4;C=1"],
                        [3, "A=1;B=3;C=2"]],
                         columns=["ID", "INFO"])
        
        print(df.INFO.str.findall(r'=(\d+)'))
        # 0    [2, 2, 5]
        # 1    [3, 4, 1]
        # 2    [1, 3, 2]
        
        df[["A", "B", "C"]] = df.INFO.str.findall(r'=(\d+)').apply(pd.Series)
        print(df)
        #    ID         INFO  A  B  C
        # 0   1  A=2;B=2;C=5  2  2  5
        # 1   2  A=3;B=4;C=1  3  4  1
        # 2   3  A=1;B=3;C=2  1  3  2
        
        # Remove INFO column
        df = df.drop("INFO", 1)
        print(df)
        #    ID  A  B  C
        # 0   1  2  2  5
        # 1   2  3  4  1
        # 2   3  1  3  2
        

        【讨论】:

          【解决方案5】:

          另一种解决方案:

            #split on ';'
            #explode
            #then split on '='
            #and pivot
            df_INFO = (df.INFO
                       .str.split(';')
                       .explode()
                       .str.split('=',expand=True)
                       .pivot(columns=0,values=1)
                       )
          
             pd.concat([df.ID,df_INFO],axis=1)
          
              ID  A   B   C
          0   1   2   2   5
          1   2   3   4   1
          2   3   1   3   2
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2021-03-05
            • 2018-03-17
            • 2016-09-10
            • 1970-01-01
            • 1970-01-01
            • 2019-09-23
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多