【问题标题】:pandas.DataFrame.drop_duplicates(inplace=True) Throws 'TypeError: unhashable type: 'dict''pandas.DataFrame.drop_duplicates(inplace=True) 抛出 'TypeError: unhashable type: 'dict''
【发布时间】:2018-08-01 00:49:17
【问题描述】:

这是我的代码:

块 1

import requests
import pandas as pd

url = ('http://www.omdbapi.com/' '?apikey=ff21610b&t=social+network')
r = requests.get(url)
json_data = r.json()
# from app
print(json_data['Awards'])
json_dict = dict(json_data)
tab=""
# printing all data as Dictionary
print("JSON as Dictionary (all):\n")
for k,v in json_dict.items():
  if len(k) > 6:
    tab = "\t"
  else:
    tab = "\t\t"
  print(str(k) + ":" + tab + str(v))
df = pd.DataFrame(json_dict)
df.drop_duplicates(inplace=True)
# printing Pandas DataFrame of all data
print("JSON as DataFrame (all):\n{}".format(df))

我只是在 DataCamp 上测试一个示例问题。然后我开始探索不同的事物。问题停在print(json_data['Awards'])。我更进一步,正在测试将 JSON 文件转换为字典并创建它的 pandas DataFrame。有趣的是,我的输出如下:

Won 3 Oscars. Another 165 wins & 168 nominations.
JSON as Dictionary (all):

Title:      The Social Network
Year:       2010
Rated:      PG-13
Released:   01 Oct 2010
Runtime:    120 min
Genre:      Biography, Drama
Director:   David Fincher
Writer:     Aaron Sorkin (screenplay), Ben Mezrich (book)
Actors:     Jesse Eisenberg, Rooney Mara, Bryan Barter, Dustin Fitzsimons
Plot:       Harvard student Mark Zuckerberg creates the social networking site that would become known as Facebook, but is later sued by two brothers who claimed he stole their idea, and the co-founder who was later squeezed out of the business.
Language:   English, French
Country:    USA
Awards:     Won 3 Oscars. Another 165 wins & 168 nominations.
Poster:     https://m.media-amazon.com/images/M/MV5BMTM2ODk0NDAwMF5BMl5BanBnXkFtZTcwNTM1MDc2Mw@@._V1_SX300.jpg
Ratings:    [{'Source': 'Internet Movie Database', 'Value': '7.7/10'}, {'Source': 'Rotten Tomatoes', 'Value': '96%'}, {'Source': 'Metacritic', 'Value': '95/100'}]
Metascore:  95
imdbRating: 7.7
imdbVotes:  542,658
imdbID:     tt1285016
Type:       movie
DVD:        11 Jan 2011
BoxOffice:  $96,400,000
Production: Columbia Pictures
Website:    http://www.thesocialnetwork-movie.com/
Response:   True
Traceback (most recent call last):
  File "C:\Users\rschosta\OneDrive - Incitec Pivot Limited\Documents\Data Science\omdb-api-test.py", line 20, in <module>
    df.drop_duplicates(inplace=True)
  File "C:\Users\rschosta\AppData\Local\Continuum\anaconda3\lib\site-packages\pandas\core\frame.py", line 3535, in drop_duplicates
    duplicated = self.duplicated(subset, keep=keep)
  File "C:\Users\rschosta\AppData\Local\Continuum\anaconda3\lib\site-packages\pandas\core\frame.py", line 3582, in duplicated
    labels, shape = map(list, zip(*map(f, vals)))
  File "C:\Users\rschosta\AppData\Local\Continuum\anaconda3\lib\site-packages\pandas\core\frame.py", line 3570, in f
    vals, size_hint=min(len(self), _SIZE_HINT_LIMIT))
  File "C:\Users\rschosta\AppData\Local\Continuum\anaconda3\lib\site-packages\pandas\core\algorithms.py", line 471, in factorize
    labels = table.get_labels(values, uniques, 0, na_sentinel, check_nulls)
  File "pandas/_libs/hashtable_class_helper.pxi", line 1367, in pandas._libs.hashtable.PyObjectHashTable.get_labels
TypeError: unhashable type: 'dict'

我正在对 .drop_duplicates() 进行一些研究,因为我以前使用过它并且它工作得很好。这是一个运行良好的示例代码:

第 2 块

import pandas as pd
import numpy as np

#Create a DataFrame
d = {
    'Name':['Alisa','Bobby','jodha','jack','raghu','Cathrine',
            'Alisa','Bobby','kumar','Alisa','Alex','Cathrine'],
    'Age':[26,24,23,22,23,24,26,24,22,23,24,24],

    'Score':[85,63,55,74,31,77,85,63,42,62,89,77]}

df = pd.DataFrame(d,columns=['Name','Age','Score'])
print(df)
df.drop_duplicates(keep=False, inplace=True)
print(df)

请注意,这两个代码块存在一些差异。我在我的第一个脚本中将 numpy 作为 np 导入,它并没有改变结果。

关于如何使 drop_duplicates() 方法在 BLOCK 1 上工作的任何想法?

输出块 1 - A

根据@Wen 的要求,这里是字典形式的数据:

{'Title': 'The Social Network', 'Year': '2010', 'Rated': 'PG-13', 'Released': '01 Oct 2010', 'Runtime': '120 min', 'Genre': 'Biography, Drama', 'Director': 'David Fincher', 'Writer': 'Aaron Sorkin (screenplay), Ben Mezrich (book)', 'Actors': 'Jesse Eisenberg, Rooney Mara, Bryan Barter, Dustin Fitzsimons', 'Plot': 'Harvard student Mark Zuckerberg creates the social networking site that would become known as Facebook, but is later sued by two brothers who claimed he stole their idea, and the co-founder who was later squeezed out of the business.', 'Language': 'English, French', 'Country': 'USA', 'Awards': 'Won 3 Oscars. Another 165 wins & 168 nominations.', 'Poster': 'https://m.media-amazon.com/images/M/MV5BMTM2ODk0NDAwMF5BMl5BanBnXkFtZTcwNTM1MDc2Mw@@._V1_SX300.jpg', 'Ratings': [{'Source': 'Internet Movie Database', 'Value': '7.7/10'}, {'Source': 'Rotten Tomatoes', 'Value': '96%'}, {'Source': 'Metacritic', 'Value': '95/100'}], 'Metascore': '95', 'imdbRating': '7.7', 'imdbVotes': '542,658', 'imdbID': 'tt1285016', 'Type': 'movie', 'DVD': '11 Jan 2011', 'BoxOffice': '$96,400,000', 'Production': 'Columbia Pictures', 'Website': 'http://www.thesocialnetwork-movie.com/', 'Response': 'True'}

现在我没有调用.drop_duplicates() 方法,同时我正在删除重复项之前将评级字典转换为列,我在打印的字典的表格列表中也有更多输出,这更容易一些阅读:

Title:      The Social Network
Year:       2010
Rated:      PG-13
Released:   01 Oct 2010
Runtime:    120 min
Genre:      Biography, Drama
Director:   David Fincher
Writer:     Aaron Sorkin (screenplay), Ben Mezrich (book)
Actors:     Jesse Eisenberg, Rooney Mara, Bryan Barter, Dustin Fitzsimons
Plot:       Harvard student Mark Zuckerberg creates the social networking site that would become known as Facebook, but is later sued by two brothers who claimed he stole their idea, and the co-founder who was later squeezed out of the business.
Language:   English, French
Country:    USA
Awards:     Won 3 Oscars. Another 165 wins & 168 nominations.
Poster:     https://m.media-amazon.com/images/M/MV5BMTM2ODk0NDAwMF5BMl5BanBnXkFtZTcwNTM1MDc2Mw@@._V1_SX300.jpg
Ratings:    [{'Source': 'Internet Movie Database', 'Value': '7.7/10'}, {'Source': 'Rotten Tomatoes', 'Value': '96%'}, {'Source': 'Metacritic', 'Value': '95/100'}]
Metascore:  95
imdbRating: 7.7
imdbVotes:  542,658
imdbID:     tt1285016
Type:       movie
DVD:        11 Jan 2011
BoxOffice:  $96,400,000
Production: Columbia Pictures
Website:    http://www.thesocialnetwork-movie.com/
Response:   True

【问题讨论】:

  • 您是否愿意在块 1 中发布您的示例数据
  • @Wen 样本数据在输出中。我将添加我的新输出和代码。

标签: python pandas dataframe


【解决方案1】:

您有一个Ratings 列,其中充满了字典。所以你不能使用drop_duplicates 因为dicts 是可变的而不是可散列的。

作为一种解决方案,您可以将transform 这些值作为元组的frozenset,然后使用drop_duplicates

df['Ratings'] = df.Ratings.transform(lambda k: frozenset(k.items()))
df.drop_duplicates()

或者只选择您想用作参考的列。例如,如果您只想删除基于yeartitle 的重复项,您可以执行类似的操作

ref_cols = ['Title', 'Year']
df.loc[~df[ref_cols].duplicated()]

【讨论】:

  • 感谢您指出df['Ratings'] 列中的字典。您的解决方案要么让我丢失 Ratings Source 和 Value 数据,要么将字典转换为 frozenset,除了 Ratings 列之外,我仍然会有大部分重复数据,并且不需要 .drop_duplicates()。在应用.drop_duplicates() 之前,我正在将评级字典转换为df.drop() df['Ratings'] 的列。
  • 感谢您的回答。它并没有给我我想要的 1 行。我正在努力并取得进展。再次感谢 RafaelC 和 Wen 的帮助。
【解决方案2】:

Object 通常会产生这些问题,一种方法是将dictlist 转换为str

df['Ratings1'] = df.Ratings.astype(str)
df=df.drop_duplicates(df.columns.difference(['Ratings'])).drop('Ratings1')

【讨论】:

  • @Wen 谢谢你。这是好东西。我正在努力将df['Ratings'] 的每个字典值放入它们自己的列中。我创建了一个创建列名的工作 for 循环。这是一项正在进行的工作。然后我可以删除重复项。
  • 这正是我想要的。谢谢!
猜你喜欢
  • 2021-08-31
  • 1970-01-01
  • 2020-12-10
  • 1970-01-01
  • 2015-11-24
  • 1970-01-01
  • 2016-01-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多