【问题标题】:Unable to extract unique words from a CSV无法从 CSV 中提取唯一词
【发布时间】:2017-01-16 00:31:34
【问题描述】:

我有一个csv,如下所示:

    Description
0   ['boy']
1   ['boy', 'jumped', 'roof']
2   ['paris']
3   ['paris', 'beautiful', 'new', 'york']
4   ['lets', 'go', 'party']
5   ['refused', 'come', 'party']

我需要从这些数据中找出唯一的词。所以输出将是:

    Unique Words
0   boy
1   jumped
2   roof
3   paris
4   beautiful
5   new
6   york

以此类推。我正在尝试使用 Pandas 和 Python 来做到这一点,但无法实现。我的代码是:

df = pd.read_csv('output.csv')
list(set(df.Description))
g = list(df['Description'].unique())
print(g)

这会抛出错误的输出,它只会抛出原始的 csv 数据帧。

【问题讨论】:

  • 我怀疑您的数据框的列包含其元素是这些单词的列表,或者它包含字符串格式的列表,即每行包含所有单词的长字符串。无论哪种方式,它都会对这些列表/完整字符串而不是单个字符串执行 unique 操作。

标签: python list csv pandas unique


【解决方案1】:

您可以先将string 列转换为list,我使用ast.literal_eval。然后通过列表理解制作列表的平面列表,使用set,最后通过构造函数创建新的DataFrame

import ast

print (type(df.ix[0, 'Description']))
<class 'str'>

df.Description = df.Description.apply(ast.literal_eval)

print (type(df.ix[0, 'Description']))
<class 'list'>

#http://stackoverflow.com/q/952914/2901002
unique_data = list(set([item for sublist in df.Description.tolist() for item in sublist]))
print (unique_data)
['refused', 'jumped', 'go', 'roof', 'come', 'beautiful',
 'paris', 'york', 'lets', 'new', 'boy', 'party']

print (pd.DataFrame({'Unique Words': unique_data}))
   Unique Words
0       refused
1        jumped
2            go
3          roof
4          come
5     beautiful
6         paris
7          york
8          lets
9           new
10          boy
11        party

没有ast的另一种解决方案:

df.Description = df.Description.str.strip('[]').str.split(',')
print (df)
                                Description
0                                   ['boy']
1               ['boy',  'jumped',  'roof']
2                                 ['paris']
3  ['paris',  'beautiful',  'new',  'york']
4                 ['lets',  'go',  'party']
5            ['refused',  'come',  'party']

unique_data = list(set([item.strip().strip("'") for sublist in df.Description.tolist() for item in sublist]))
print (unique_data)
['refused', 'jumped', 'go', 'roof', 'come', 'beautiful', 
'paris', 'york', 'lets', 'new', 'boy', 'party']

print (pd.DataFrame({'Unique Words': unique_data}))
   Unique Words
0       refused
1        jumped
2            go
3          roof
4          come
5     beautiful
6         paris
7          york
8          lets
9           new
10          boy
11        party

【讨论】:

  • 没有ast的解决方案是最快的。
【解决方案2】:

这种方法有效:

import pandas as pd
import ast

test = {'Description':["['boy']","['boy', 'jumped', 'roof']","['paris']",\
 "['paris', 'beautiful', 'new', 'york']","['lets', 'go', 'party']",\
 "['refused', 'come', 'party']"]}

tt = pd.DataFrame(test)

listOfWords = []
for i,row in tt.iterrows():
  listOfWords.extend(ast.literal_eval(tt.ix[i,'Description']))
uniqueWords = pd.DataFrame(listOfWords,columns=['Unique Words']).drop_duplicates()

如果你想要它排序:

uniqueWords = uniqueWords.sort_values('Unique Words')

您遍历所有行,将字符串转换为列表,然后使用extend 将所有这些列表收集到一个长列表中。然后从该列表中创建一个新的 DataFrame 并删除重复项。

编辑:感谢 jezrael 纠正我的解决方案,我从他的解决方案中借用了 ast.literal_eval 方法。

我尝试使用%timeit 命令比较我们的解决方案,但在两个解决方案中都得到ValueError: malformed stringast.literal_eval

EDIT2:对于我们这里的小数据示例,jezrael 的解决方案速度是原来的两倍。

EDIT3:我无法使用大数据示例进行测试(将给定的数字乘以某个数字),因为 timeit 不断抛出 malformed string 错误,原因我不清楚。

EDIT4:让它以某种方式工作。对于更大的数据集(6000 行),jezrael 的解决方案要快 8 倍以上。与列表推导相比,即使使用 iterrows 进行迭代也相当慢。我还测试了没有ast 的jezrael 的第二个解决方案。这比他的第一个解决方案快两倍多。

【讨论】:

  • 只有问题OP读取csv,所以type的值input dfstrings,看起来像lists
  • 你说得对,我会尽快更正并比较解决方案。
  • 你的更快。 :)
猜你喜欢
  • 1970-01-01
  • 2015-11-23
  • 2020-04-17
  • 1970-01-01
  • 2018-11-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多