【问题标题】:Python: Pandas filter string data based on its string lengthPython:Pandas 根据字符串长度过滤字符串数据
【发布时间】:2013-11-25 02:02:34
【问题描述】:

我喜欢过滤掉字符串长度不等于10的数据。

如果我尝试过滤掉 A 列或 B 列的字符串长度不等于 10 的任何行,我尝试了这个。

df=pd.read_csv('filex.csv')
df.A=df.A.apply(lambda x: x if len(x)== 10 else np.nan)
df.B=df.B.apply(lambda x: x if len(x)== 10 else np.nan)
df=df.dropna(subset=['A','B'], how='any')

这运行缓慢,但正在运行。

但是,当A中的数据不是字符串而是数字(read_csv读取输入文件时解释为数字)时,有时会产生错误。

  File "<stdin>", line 1, in <lambda>
TypeError: object of type 'float' has no len()

我相信应该有更高效和优雅的代码来代替这个。


根据下面的答案和cmets,我找到的最简单的解决方案是:

df=df[df.A.apply(lambda x: len(str(x))==10]
df=df[df.B.apply(lambda x: len(str(x))==10]

df=df[(df.A.apply(lambda x: len(str(x))==10) & (df.B.apply(lambda x: len(str(x))==10)]

df=df[(df.A.astype(str).str.len()==10) & (df.B.astype(str).str.len()==10)]

【问题讨论】:

    标签: python string pandas csv filter


    【解决方案1】:

    如果您在行中有数字,那么它们将转换为浮点数。

    从 cvs 导入后将所有行转换为字符串。为了获得更好的性能,将 lambda 拆分为多个线程。

    【讨论】:

      【解决方案2】:
      import pandas as pd
      
      df = pd.read_csv('filex.csv')
      df['A'] = df['A'].astype('str')
      df['B'] = df['B'].astype('str')
      mask = (df['A'].str.len() == 10) & (df['B'].str.len() == 10)
      df = df.loc[mask]
      print(df)
      

      应用于filex.csv:

      A,B
      123,abc
      1234,abcd
      1234567890,abcdefghij
      

      上面的代码打印出来

                  A           B
      2  1234567890  abcdefghij
      

      【讨论】:

        【解决方案3】:

        根据其他列的给定条件及其值过滤出行的更 Pythonic 方式:

        假设 df 为:

        data={"names":["Alice","Zac","Anna","O"],"cars":["Civic","BMW","Mitsubishi","Benz"],
             "age":["1","4","2","0"]}
        
        df=pd.DataFrame(data)
        df:
          age        cars  names
        0   1       Civic  Alice
        1   4         BMW    Zac
        2   2  Mitsubishi   Anna
        3   0        Benz      O
        

        然后:

        df[
        df['names'].apply(lambda x: len(x)>1) &
        df['cars'].apply(lambda x: "i" in x) &
        df['age'].apply(lambda x: int(x)<2)
          ]
        

        我们将有:

          age   cars  names
        0   1  Civic  Alice
        

        在上述条件中,我们首先查看字符串的长度,然后检查字符串中是否存在字母(“i”),最后检查第一列中整数的值。

        【讨论】:

          【解决方案4】:

          您可以使用 df.apply(len) 。它会给你结果

          【讨论】:

            【解决方案5】:

            我个人觉得这种方式最简单:

            df['column_name'] = df[df['column_name'].str.len()!=10]
            

            【讨论】:

            • 虽然起初这似乎更方便,但比使用 apply 慢,尤其是在更大的数据集上。
            【解决方案6】:

            从 A 列和 B 列中过滤掉长度为 10 的值,这里我将 lambda 表达式传递给 map() 函数。 map() 函数始终适用于 Series 对象。

             df = df[df['A'].map(lambda x: len(str(x)) == 10)]
             df = df[df['B'].map(lambda x: len(str(x)) == 10)]
            

            【讨论】:

            • 如果您解释了您提供的代码如何回答问题,这将是一个更好的答案。
            【解决方案7】:

            您可以使用 applymap 一次过滤您想要的所有列,然后使用 .all() 方法仅过滤两列都为 True 的行。

            #The *mask* variable is a dataframe of booleans, giving you True or False for the selected condition
            mask = df[['A','B']].applymap(lambda x: len(str(x)) == 10)
            
            #Here you can just use the mask to filter your rows, using the method *.all()* to filter only rows that are all True, but you could also use the *.any()* method for other needs
            df = df[mask.all(axis=1)]
            

            【讨论】:

              猜你喜欢
              • 2019-02-04
              • 1970-01-01
              • 2012-12-06
              • 2012-01-19
              • 2022-01-03
              • 2012-11-23
              • 2018-09-16
              • 2016-07-08
              相关资源
              最近更新 更多