【问题标题】:How to remove duplicate items from dict type dataframe using python pandas?如何使用 python pandas 从 dict 类型数据框中删除重复项?
【发布时间】:2021-03-04 12:10:07
【问题描述】:

我有下面的数据框重复数据。我想从数据框中删除这些重复项。

df = pd.DataFrame({'test_id': [
        {'user_id':2, 'insert_date':'2020-12-23', 'is_admin': "true"},
        {'user_id':4, 'insert_date':'2020-12-23', 'is_admin': "true"},
        {'user_id':3, 'insert_date':'2020-12-21', 'is_admin': "false"},
        {'user_id':2, 'insert_date':'2020-12-23', 'is_admin': "true"}
    ], 'contact_id':[1,4,2,1]}
)

print(df)

                                             test_id  contact_id
0  {'user_id': 2, 'insert_date': '2020-12-23', 'i...           1
1  {'user_id': 4, 'insert_date': '2020-12-23', 'i...           4
2  {'user_id': 3, 'insert_date': '2020-12-21', 'i...           2
3  {'user_id': 2, 'insert_date': '2020-12-23', 'i...           1

我已尝试在下面删除重复项

df = df.drop_duplicates(subset=['test_id', 'contact_id'], keep='first')
print(df)

但是遇到错误

TypeError: unhashable type: 'dict'

谁能指导我如何删除基于“test_id”、“contact_id”组合的重复数据?

我想要下面的输出

                                             test_id  contact_id
0  {'user_id': 2, 'insert_date': '2020-12-23', 'i...           1
1  {'user_id': 4, 'insert_date': '2020-12-23', 'i...           4
2  {'user_id': 3, 'insert_date': '2020-12-21', 'i...           2

【问题讨论】:

    标签: python pandas dataframe


    【解决方案1】:

    您可以先将test_id 列中的值转换为字符串,然后再删除重复项:

    df['test_id'] = df['test_id'].astype(str)
    

    然后运行你的代码:

    df = df.drop_duplicates(subset=['test_id', 'contact_id'], keep='first')
    print(df)
    

    输出和你想要的一样:

                                                 test_id  contact_id
    0  {'user_id': 2, 'insert_date': '2020-12-23', 'i...           1
    1  {'user_id': 4, 'insert_date': '2020-12-23', 'i...           4
    2  {'user_id': 3, 'insert_date': '2020-12-21', 'i...           2
    

    编辑

    您可以通过以下代码将test_id列的数据类型从str恢复为dict

    df['test_id'] = df['test_id'].map(eval)
    

    或者,您也可以考虑以下代码,这通常被认为比使用eval(如果数据来自外部源)更安全:

    import ast
    
    df["test_id"] = df["test_id"].map(ast.literal_eval) 
    

    查看帖子Using python's eval() vs. ast.literal_eval()?了解更多信息。

    在任何一段代码之后,您都可以像往常一样执行 dict/json 操作:

    type(df.loc[2, 'test_id'])            gets: dict
    df.loc[2, 'test_id']['insert_date']   gets: '2020-12-21'
    df.loc[2, 'test_id']['user_id']       gets: 3
    
    df['test_id'].to_list()               gets the list of dict instead of list of str:
        [{'user_id': 2, 'insert_date': '2020-12-23', 'is_admin': 'true'},
         {'user_id': 4, 'insert_date': '2020-12-23', 'is_admin': 'true'},
         {'user_id': 3, 'insert_date': '2020-12-21', 'is_admin': 'false'},
         {'user_id': 2, 'insert_date': '2020-12-23', 'is_admin': 'true'}]
    

    【讨论】:

    • 您的回答是正确的,但转换为 str 不会用于其他功能。所以@Jezrael 的答案是准确的。所以接受他的回答,但我赞成你的回答。
    • 转换为str后,如何将test_id列再次转换为JSON
    • @SangramBadi,试试:import astdf["test_id"] = df["test_id"].map(ast.literal_eval)
    • @SangramBadi 更简单的方法是使用:df['test_id'] = df['test_id'].map(eval)。请参阅上面的编辑。
    【解决方案2】:

    您可以使用Series.duplicated 并按原始值过滤boolean indexing,因此原始字典不会更改:

    您可以通过json_normalize将字典转换为DataFrame:

    print(pd.json_normalize(df['test_id']))
       user_id insert_date is_admin
    0        2  2020-12-23     true
    1        4  2020-12-23     true
    2        3  2020-12-21    false
    3        2  2020-12-23     true
    
    df = df[~pd.json_normalize(df['test_id']).assign(new = df['contact_id']).duplicated()]
    print (df)
                                                 test_id  contact_id
    0  {'user_id': 2, 'insert_date': '2020-12-23', 'i...           1
    1  {'user_id': 4, 'insert_date': '2020-12-23', 'i...           4
    2  {'user_id': 3, 'insert_date': '2020-12-21', 'i...           2
    

    如果转换为字符串时顺序总是相同的:

    df = df[~df[['test_id']].astype(str).assign(new = df['contact_id'].duplicated()]
    print (df)
                                                 test_id  contact_id
    0  {'user_id': 2, 'insert_date': '2020-12-23', 'i...           1
    1  {'user_id': 4, 'insert_date': '2020-12-23', 'i...           4
    2  {'user_id': 3, 'insert_date': '2020-12-21', 'i...           2
    

    【讨论】:

    • 您的答案比@SeaBean 的答案更准确。所以接受并支持你的答案
    • @SangramBadi - 谢谢。
    • 我收到type object 'Series' has no attribute '_get_dtypes' 错误,同时使用modin.pandas 部署在linux 服务器中
    猜你喜欢
    • 2013-06-01
    • 2020-11-09
    • 2020-12-23
    • 1970-01-01
    • 1970-01-01
    • 2019-05-12
    • 2021-10-26
    • 2021-04-22
    • 2018-01-21
    相关资源
    最近更新 更多