【问题标题】:pandas getting most frequent names from a column which has list of names熊猫从具有名称列表的列中获取最常用的名称
【发布时间】:2018-12-12 05:08:26
【问题描述】:

我的数据框是这样的

star_rating  actors_list
0   9.3     [u'Tim Robbins', u'Morgan Freeman']
1   9.2     [u'Marlon Brando', u'Al Pacino', u'James Caan']
2   9.1     [u'Al Pacino', u'Robert De Niro']
3   9.0     [u'Christian Bale', u'Heath Ledger']
4   8.9     [u'John Travolta', u'Uma Thurman']

我想提取actors_list 列中出现频率最高的名字。我找到了这段代码。你有更好的建议吗?尤其是对于大数据。

import pandas as pd
df= pd.read_table (r'https://raw.githubusercontent.com/justmarkham/pandas-videos/master/data/imdb_1000.csv',sep=',')
df.actors_list.str.replace("(u\'|[\[\]]|\')",'').str.lower().str.split(',',expand=True).stack().value_counts()

(this data) 的预期输出

robert de niro    13
tom hanks         12
clint eastwood    11
johnny depp       10
al pacino         10
james stewart      9

【问题讨论】:

  • 提供预期的输出。
  • 使用 for 循环总是比把繁重的工作交给 pandas 本身要好。
  • @coldspeed 我不认为这是取消嵌套的骗局。
  • 如果你的列表很大,那么expand=True 会杀死你的系统。
  • @Dark 没有expand=True .stack() 不起作用

标签: python python-3.x pandas dataframe


【解决方案1】:

根据我的测试,计数后进行正则表达式清理会快得多。

from itertools import chain
import re

p = re.compile("""^u['"](.*)['"]$""")
ser = pd.Series(list(chain.from_iterable(
    x.title().split(', ') for x in df.actors_list.str[1:-1]))).value_counts()
ser.index = [p.sub(r"\1", x) for x in ser.index.tolist()]


ser.head()

Robert De Niro    18
Brad Pitt         14
Clint Eastwood    14
Tom Hanks         14
Al Pacino         13
dtype: int64

【讨论】:

  • 也许最好删除from collections import Counter并将.title()添加到x.title().split(', ')
【解决方案2】:

使用纯 python 总是比依赖 pandas 更好,因为如果列表很大,它会消耗大量内存。

如果列表的大小为 1000,那么当您使用 expand = True 时,非 1000 长度的列表将包含 Nan,这会浪费内存。试试这个。

df = pd.concat([df]*1000) # For the sake of large df. 

%%timeit
df.actors_list.str.replace("(u\'|[\[\]]|\')",'').str.lower().str.split(',',expand=True).stack().value_counts()
10 loops, best of 3: 65.9 ms per loop

%%timeit     
df['actors_list'] = df['actors_list'].str.strip('[]').str.replace(', ',',').str.split(',')
10 loops, best of 3: 24.1 ms per loop

%%timeit
words = {}
for i in df['actors_list']:
    for w in i : 
        if w in words:
            words[w]+=1
        else:
            words[w]=1

100 loops, best of 3: 5.44 ms per loop

【讨论】:

  • 别忘了给这部分计时:df['actors_list'].str.strip('[]').str.replace(', ',',').str.split(',')
  • @Dark:您的代码出现Can only use .str accessor with string values, which use np.object_ dtype in pandas 错误。也是你执行代码的地方。在 jupyter notebook 和 Ipython 他们不接受 %%。
  • @Rezaenergy 删除%%timeit 部分及其结果,仅使用代码。由于数据类型建议为对象,您可以直接运行以words={} 开头的代码。
  • @Dark 谢谢它没有 %timeit 或 %%timeit 它可以工作,但我不知道什么时候添加 %%timeit 它会导致这个错误Can only use .str accessor with string values, which use np.object_ dtype in pandas
【解决方案3】:

我将使用ast 将列表转换为list

import ast 
df.actors_list=df.actors_list.apply(ast.literal_eval)
pd.DataFrame(df.actors_list.tolist()).melt().value.value_counts()

【讨论】:

  • 显示错误ValueError: malformed node or string: ['Tim Robbins', 'Morgan Freeman', 'Bob Gunton']
【解决方案4】:

根据this code我得到了下面的图表

其中

  • coldspeed 的代码是 wen2()
  • Dark 的代码是 wen4()
  • 我的代码是 wen1()
  • W-B 的代码是 wen3()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-02-17
    • 2017-02-20
    • 1970-01-01
    • 1970-01-01
    • 2016-06-24
    • 2017-03-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多