【问题标题】:getting error while removing duplicates from csv using pandas使用 pandas 从 csv 中删除重复项时出错
【发布时间】:2019-04-23 19:47:45
【问题描述】:

我的 csv 文件位于此链接:

https://drive.google.com/file/d/1Pac9-YLAtc7iaN0qEuiBOpYYf9ZPDDaL/view?usp=sharing

我想通过检查每个艺术家 ID 的 genres 长度来从 csv 中删除重复项。如果艺术家在 csv 中有 2 条记录(例如,ed sheeran 的 id 6eUKZXaKkcviH0Ku9w2n3V 有 2 条记录,一条记录有 1 个流派,而第 5 行有 5 个流派,所以我想保留流派长度最大的行)

我现在正在使用这个脚本:

import pandas
import ast


df = pandas.read_csv('39K.csv', encoding='latin-1')

df['lst_len'] = df['genres'].map(lambda x: len(ast.literal_eval(str(x))))
print(df['lst_len'][0])

df = df.sort_values('lst_len', ascending=False)

# Drop duplicates, preserving first (longest) list by ID
df = df.drop_duplicates(subset='ID')


# Remove extra column that we introduced, write to file
df = df.drop('lst_len', axis=1)
df.to_csv('clean_39K.csv', index=False)

但此脚本适用于 500 条记录(可能我错觉记录的大小很重要),

但是当我为我最大的文件 39K.csv 运行这个脚本时,我收到了这个错误:

Traceback (most recent call last):
******* error in line 5, in <module>....
    df['lst_len'] = df['genres'].map(lambda x: len(list(x)))
    df['lst_len'] = df['genres'].map(lambda x: len(list(x)))
TypeError: 'float' object is not iterable

请指出我做错了什么? 谢谢

【问题讨论】:

    标签: python pandas csv


    【解决方案1】:

    您的输入 csv 文件的(至少)第 16553 行有错误数据:

    52lUXCmpmAIVsgNd1uADOy,Moosh & Twist,NULL
    

    pandas 在读取文件时将NULL 解释为nan,该文件的类型为float,并且不可迭代。那里还有一些其他 NULL 条目,因此您可以手动删除或修复它们(首选),或者在您的代码中处理这种情况。

    例如,如果你真的想假装 NULL 应该被解释为一个空列表,你可以像这样预处理数据(在读取 csv 之后):

    df.loc[df['genres'].isnull(),['genres']] = df.loc[df['genres'].isnull(),'genres'].apply(lambda x: [])
    

    或者更优雅,切换到使用na_filter=False读取csv:

    df = pandas.read_csv('39K.csv', encoding='latin-1', na_filter=False)
    

    这将首先阻止 pandas 将这些值替换为 nan

    最后,代码并没有完全按照我们的 ant 操作,因为它正在计算列表的字符串表示形式中的字符数。解决方案是将NULL值预处理为代表空列表的字符串,然后使用ast.literal_eval将所有字符串转回列表:

    import pandas
    import ast
    
        df = pandas.read_csv('39K.csv', encoding='latin-1', na_filter=False)
        df.replace(to_replace="NULL", value="[]", inplace=True)
    
        for item in df['genres']:
    
            print(str(item))
            print(ast.literal_eval(item))
    
        df['lst_len'] = df['genres'].map(lambda x: len(ast.literal_eval(x)))
    

    【讨论】:

    • 或者也许值得使用 DataFrame.fillna("0") 或在整个数据帧中使用空白进行预处理。
    • @pygo 我是这么想的,但我不确定这是否可行,因为fillna 不接受列表作为其参数,我们明确需要一个空列表,因为我们稍后会计算它的长度。如果没有进一步处理,使用fillna("0") 肯定行不通(经过测试)。
    • 嗯,df = df.fillna('') 怎么样,它将用 '' 即空填充 na(例如 NaN),或者 df.read_csv(path , na_filter=False) 默认将空字段视为空字符串。
    • @pygo 使用fillna('') 仍然不起作用,这些值仍然是nan。但是您对na_filter=False 的想法非常有效,谢谢,我已将其编辑为答案。
    • @RobBricheno,太棒了!
    猜你喜欢
    • 2020-04-01
    • 2018-03-24
    • 2013-03-29
    • 2019-08-04
    • 1970-01-01
    • 2019-03-09
    • 2016-03-29
    • 2023-03-27
    • 2015-11-02
    相关资源
    最近更新 更多