【问题标题】:String splitting loop through Dataframe通过Dataframe进行字符串拆分循环
【发布时间】:2014-09-11 06:24:31
【问题描述】:

我正在尝试使用 Python 循环遍历格式如下的数据框列:

Town 1, AL, USA
Town 2, AL, USA
Town 3, AK, USA
Town 4, CA, USA
Town 5, DE, USA
Town 6, MI, USA

我一直在尝试将 split() 方法与原始数据框(包括犯罪描述和 URL 列)和单独的列一起作为数据框和系列对象。这些对象都没有可用的方法 split()。

所需的输出将是仅包含 STATE 缩写的另一列,因此我知道我正在尝试找到 df.split(', ') 的等效项,并从该拆分中为系列或数据帧附加第二个 [1] 索引。 (如果我错了,请纠正我)。

我该怎么做呢?

【问题讨论】:

    标签: python string pandas split dataframe


    【解决方案1】:

    函数split_str_columns_df 循环一次拆分所有字符串列。

    还生成带有拆分的新列,并删除旧列。

    您选择您的拆分器:" ""," 或 ....

    只需在上面看到的函数定义中引入即可:

    new = df[col].str.split(" ", n = 1, expand = True) 
    

    或者如果你想要一个 , 并分成 3 列 (n=2),你必须稍微调整一下函数以合并第 3 列

    new = df[col].str.split(", ", n = 2, expand = True) 
    

    示例数据:(整个示例数据位于本文末尾)

    data_df.head(3)
    

    .

        Rating          Score    Ocupation
    0   RATINGSTUFE F   NaN      Animator Senior
    1   RATINGSTUFE B   4.0      Animator
    2   NaN             7.0      Art administrator
    

    调用函数:split_str_columns_df(data_df,columns)

    我要拆分的列是'Rating''Ocupation'

    columns=['Rating','Ocupation']
    dff=split_str_columns_df(data_df,columns)
    

    输出:

       Score     Rating_a Rating_b Ocupation_a    Ocupation_b
    0    NaN  RATINGSTUFE        F    Animator         Senior
    1    4.0  RATINGSTUFE        B    Animator           None
    2    7.0          NaN      NaN         Art  administrator
    

    split_str_columns_df(data_df,columns)

    我使用的函数定义是:

    def split_str_columns_df(dataframe,str_columns):
        ''' Function that splits the str columns " " is the separation, create 2 new 
            columns and remove the original. If the column's name is 'Name' the 2 new columns will be 'Name_a' and 'Name_b'.'''
        # new data frame with split value columns 
        df=dataframe
        for i in range(len(str_columns)):
            col=str_columns[i]
            new_col1=col+'_a'
            new_col2=col+'_b'
    
            #Split
            new = df[col].str.split(" ", n = 1, expand = True)   
            # making seperate first name column from new data frame 
            df[new_col1]= new[0]   
            # making seperate last name column from new data frame 
            df[new_col2]= new[1] 
    
            # Dropping old Name columns 
            df.drop(columns =[col], inplace = True)     
        return df
    

    注意!

    1. 拆分 NaN 值时,新的 2 列得到 nan(两者)(Col Rating_a, Rating_b

    2. 如果一行包含 1 个单词,当您拆分第二列时,您将获得 None(列 Ocupation_b

    3. 意识到原来的列RatingOcupations被删除了,我们有 Rating_aRating_b。还有Ocupations_aOcupations_b

    生成例子的数据:

    data_df=pd.DataFrame(['RATINGSTUFE F', 'RATINGSTUFE B',np.nan, 'RATINGSTUFE L',
       'RATINGSTUFE G', np.nan, 'RATINGSTUFE M', 'RATINGSTUFE L',
       'RATINGSTUFE F', 'RATINGSTUFE M'], columns=['Rating'])
    
    data_df['Score']=[np.nan,4,7,4,9,4,3,1,2,5]
    data_df['Ocupation']=['Animator Senior', 'Animator', 'Art administrator', 'Animator Junior', 'Dancer', 'Colorist Junior', 'Ceramics artist', 'Chief creative officer','Colorist', 'Dancer']
    

    【讨论】:

      【解决方案2】:

      在与%timeit 比较不同方法的基础上,我发现在使用列中的字符串时,列表推导通常是赢家。

      In [1]: %paste 
      import pandas as pd
      
      data=[
          'Town 1, AL, USA',
          'Town 2, AL, USA',
          'Town 3, AK, USA',
          'Town 4, CA, USA',
          'Town 5, DE, USA',
          'Town 6, MI, USA',
      ]
      
      df = pd.DataFrame(data)
      df
      
      ## -- End pasted text --
      Out[1]: 
                       0
      0  Town 1, AL, USA
      1  Town 2, AL, USA
      2  Town 3, AK, USA
      3  Town 4, CA, USA
      4  Town 5, DE, USA
      5  Town 6, MI, USA
      

      %timeit 测试:

      In [2]: %timeit df['state'] = [x.split(',')[1] for x in df[0]]
      1000 loops, best of 3: 350 µs per loop
      
      In [3]: %timeit df['state'] = df[0].apply(lambda x: x.split(',')[1])
      1000 loops, best of 3: 671 µs per loop
      
      In [4]: %timeit df['state'] = df[0].str.split(", ").str[1]
      100 loops, best of 3: 1.1 ms per loop
      

      【讨论】:

        【解决方案3】:

        使用.apply() 对列中的每个元素执行一些函数

        import pandas as pd
        
        data=[
            'Town 1, AL, USA',
            'Town 2, AL, USA',
            'Town 3, AK, USA',
            'Town 4, CA, USA',
            'Town 5, DE, USA',
            'Town 6, MI, USA',
        ]
        
        df = pd.DataFrame( data )
        
        print df
        
        df['state'] = df[0].apply(lambda x: x.split(',')[1])
        
        print df
        

        结果

                         0
        0  Town 1, AL, USA
        1  Town 2, AL, USA
        2  Town 3, AK, USA
        3  Town 4, CA, USA
        4  Town 5, DE, USA
        5  Town 6, MI, USA
        
                         0 state
        0  Town 1, AL, USA    AL
        1  Town 2, AL, USA    AL
        2  Town 3, AK, USA    AK
        3  Town 4, CA, USA    CA
        4  Town 5, DE, USA    DE
        5  Town 6, MI, USA    MI
        

        编辑:

        顺便说一句:我在互联网上搜索pandas split column to new columns,您甚至可以通过这种方式将其拆分为 3 个新列:

        def split_more(x):
            return pd.Series( x.split(',') )
        
        df[ ['town', 'state','country'] ] = df[0].apply(split_more)
        
        print df
        

        结果:

                         0    town state country
        0  Town 1, AL, USA  Town 1    AL     USA
        1  Town 2, AL, USA  Town 2    AL     USA
        2  Town 3, AK, USA  Town 3    AK     USA
        3  Town 4, CA, USA  Town 4    CA     USA
        4  Town 5, DE, USA  Town 5    DE     USA
        5  Town 6, MI, USA  Town 6    MI     USA
        

        【讨论】:

        • 你能告诉我关于“lambda”片段到底在做什么的文档吗?
        【解决方案4】:

        您可以使用vectorized string methods,例如df["col"].str.split(", ").str[1]:

        >>> df
                       col
        0  Town 1, AL, USA
        1  Town 2, AL, USA
        2  Town 3, AK, USA
        3  Town 4, CA, USA
        4  Town 5, DE, USA
        5  Town 6, MI, USA
        >>> df["col"].str.split(", ")
        0    [Town 1, AL, USA]
        1    [Town 2, AL, USA]
        2    [Town 3, AK, USA]
        3    [Town 4, CA, USA]
        4    [Town 5, DE, USA]
        5    [Town 6, MI, USA]
        Name: col, dtype: object
        >>> df["col"].str.split(", ").str[1]
        0    AL
        1    AL
        2    AK
        3    CA
        4    DE
        5    MI
        Name: col, dtype: object
        

        【讨论】:

          【解决方案5】:

          Series have string methods 可通过其str 属性访问。例如,您可以使用 df['addr'].str.extract:

          In [34]: df = pd.read_table('data', sep='-', header=None, names=['addr'])
          
          In [35]: df
          Out[35]: 
                        addr
          0  Town 1, AL, USA
          1  Town 2, AL, USA
          2  Town 3, AK, USA
          3  Town 4, CA, USA
          4  Town 5, DE, USA
          5  Town 6, MI, USA
          
          In [36]: df[['Town', 'State', 'Country']] = df['addr'].str.extract(r'([^,]+),([^,]+),([^,]+)')
          
          In [38]: del df['addr']
          

          产量

          In [39]: df
          Out[39]: 
               Town State Country
          0  Town 1    AL     USA
          1  Town 2    AL     USA
          2  Town 3    AK     USA
          3  Town 4    CA     USA
          4  Town 5    DE     USA
          5  Town 6    MI     USA
          

          【讨论】:

          • 反响很好。最初我以为我只想保留州缩写(我正在尝试构建一个叶绿素),但使用这种方法可以让我深入到更好的细节水平,如果我这样做的话。
          猜你喜欢
          • 2014-09-19
          • 2016-04-28
          • 2020-07-06
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-03-02
          • 2013-11-23
          相关资源
          最近更新 更多