【问题标题】:Pandas Split Column熊猫拆分列
【发布时间】:2016-03-17 05:23:11
【问题描述】:

给定以下数据框:

import pandas as pd
import numpy as np
df = pd.DataFrame({
       'A' : ['a', 'b','c', 'd'],
       'B' : ['Y>`abcd', 'abcd','efgh', 'Y>`efgh']
    })
df

    A   B
0   a   Y>`abcd
1   b   abcd
2   c   efgh
3   d   Y>`efgh

我想将 '>`' 上的 A 列拆分为 2 列(C 和 D),以便我的数据

frame looks like this:
        A   C  D
    0   a   Y  abcd
    1   b      abcd
    2   c      efgh
    3   d   Y  efgh

提前致谢!

【问题讨论】:

    标签: python-3.x pandas split


    【解决方案1】:

    您可以将str.extract 与fillna 一起使用,最后一列B by drop:

    df[['C','D']] = df['B'].str.extract('(.*)>`(.*)', expand=True)
    df['D'] = df['D'].fillna(df['B'])
    df['C'] = df['C'].fillna('')
    df = df.drop('B', axis=1)
    
    print df
    
       A  C     D
    0  a  Y  abcd
    1  b     abcd
    2  c     efgh
    3  d  Y  efgh
    

    下一个解决方案使用str.split 和mask 和numpy.where:

    df[['C','D']] =  df['B'].str.split('>`', expand=True) 
    mask = pd.notnull(df['D'])
    df['D'] = df['D'].fillna(df['C'])
    df['C'] = np.where(mask, df['C'], '')
    df = df.drop('B', axis=1) 
    

    时间安排:

    在大 DataFrame 是 extract 解决方案 100 倍快,在小 1.5 倍:

    len(df)=4:

    In [438]: %timeit a(df)
    100 loops, best of 3: 2.96 ms per loop
    
    In [439]: %timeit b(df1)
    1000 loops, best of 3: 1.86 ms per loop
    
    In [440]: %timeit c(df2)
    The slowest run took 4.44 times longer than the fastest. This could mean that an intermediate result is being cached 
    1000 loops, best of 3: 1.89 ms per loop
    
    In [441]: %timeit d(df3)
    The slowest run took 4.62 times longer than the fastest. This could mean that an intermediate result is being cached 
    1000 loops, best of 3: 1.82 ms per loop
    

    len(df)=4k:

    In [443]: %timeit a(df)
    1 loops, best of 3: 799 ms per loop
    
    In [444]: %timeit b(df1)
    The slowest run took 4.19 times longer than the fastest. This could mean that an intermediate result is being cached 
    100 loops, best of 3: 7.37 ms per loop
    
    In [445]: %timeit c(df2)
    1 loops, best of 3: 552 ms per loop
    
    In [446]: %timeit d(df3)
    100 loops, best of 3: 9.55 ms per loop
    

    代码:

    import pandas as pd
    df = pd.DataFrame({
           'A' : ['a', 'b','c', 'd'],
           'B' : ['Y>`abcd', 'abcd','efgh', 'Y>`efgh']
        })
    #for test 4k    
    df = pd.concat([df]*1000).reset_index(drop=True)
    df1,df2,df3 = df.copy(),df.copy(),df.copy()
    
    def b(df):
        df[['C','D']] = df['B'].str.extract('(.*)>`(.*)', expand=True)
        df['D'] = df['D'].fillna(df['B'])
        df['C'] = df['C'].fillna('')
        df = df.drop('B', axis=1)
        return df
    
    def a(df):
        df = pd.concat([df, df.B.str.split('>').apply(
        lambda l: pd.Series({'C': l[0], 'D': l[1][1: ]}) if len(l) == 2 else \
            pd.Series({'C': '', 'D': l[0]}))], axis=1)
        del df['B']
        return df
    
    def c(df):
        df[['C','D']] = df['B'].str.split('>`').apply(lambda x: pd.Series(['']*(2-len(x)) + x))
        df = df.drop('B', axis=1)    
        return df   
    
    def d(df):
        df[['C','D']] =  df['B'].str.split('>`', expand=True) 
        mask = pd.notnull(df['D'])
        df['D'] = df['D'].fillna(df['C'])
        df['C'] = np.where(mask, df['C'], '')
        df = df.drop('B', axis=1) 
        return df  
    

    【讨论】:

    • 感谢您对这个话题的彻底处理!应用提取方法后,抛出此错误:TypeError: extract() got an unexpected keyword argument 'expand'
    • 你必须将pandas的版本更新为0.18.0,然后它就可以很好地工作了。
    【解决方案2】:

    执行str.split 后跟apply 返回pd.Series 将创建新列:

    >>> df.B.str.split('>').apply(
        lambda l: pd.Series({'C': l[0], 'D': l[1][1: ]}) if len(l) == 2 else \
            pd.Series({'C': '', 'D': l[0]}))
        C   D
    0   Y   abcd
    1       abcd
    2       efgh
    3   Y   efgh
    

    所以你可以concat这个到DataFrame,del原来的列:

    df = pd.concat([df, df.B.str.split('>').apply(
        lambda l: pd.Series({'C': l[0], 'D': l[1][1: ]}) if len(l) == 2 else \
            pd.Series({'C': '', 'D': l[0]}))],
        axis=1)
    del df['B']
    >>> df
        A   C   D
    0   a   Y   abcd
    1   b       abcd
    2   c       efgh
    3   d   Y   efgh
    

    【讨论】:

    • 这工作正常,但我只需将 [1: ] 的两个实例更改为 [0: ] 以避免由于某种原因切断 D 列每个值的第一个字符(我的真实数据)。谢谢!
    【解决方案3】:

    我会使用一个衬里:

    df['B'].str.split('>`').apply(lambda x: pd.Series(['']*(2-len(x)) + x))
    
    #   0     1
    #0  Y  abcd
    #1     abcd
    #2     efgh
    #3  Y  efgh
    

    【讨论】:

      【解决方案4】:

      最简单和最节省内存的方法是:

      df[['C', 'D']] = df.B.str.split('>`', expand=True)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-08-30
        • 1970-01-01
        • 1970-01-01
        • 2019-11-26
        • 2017-08-27
        • 1970-01-01
        相关资源
        最近更新 更多