连接大型 CSV 文件中单词的最有效方法:pandas 还是 Python 标准库? [复制]
Posted
技术标签:
【中文标题】连接大型 CSV 文件中单词的最有效方法:pandas 还是 Python 标准库? [复制]【英文标题】:Most efficient way to concatenate words from a big CSV file: pandas or Python standard library? [duplicate] 【发布时间】:2021-01-31 01:41:03 【问题描述】:我正在尝试进行文本分析,并将我的数据收集到一个包含三列的 CSV 文档中。我正在尝试将第二列中的所有文本组合成一个字符串以执行一些单词分析(词云、频率等)。我使用 pandas 导入了 CSV 文件。在下面的代码中,data
是一个DataFrame
对象。
# Extract words from comment column in data
words = " "
for msg in data["comment"]:
msg = str(msg).lower()
words = words + msg + " "
print("Length of words is:", len(words))
使用word_cloud 解析输出。
wordcloud = WordCloud(width = 3000, height = 2000, random_state=1, collocations=False, stopwords = stopwordsTerrier.union(stopwordsExtra)).generate(words)
CSV 文件
rating, comment, ID
5, It’s just soooo delicious but silly price and postage price, XXX1
5, Love this salad dressing... One my kids will estv😊, XXX2
...
该代码适用于
我的问题是:有没有更有效的方法?
【问题讨论】:
data
是什么类型的对象? data['comment']
是什么类型的对象?您确定 bottleneck 是您示例中的循环吗? 50 Mb 文件有多少行?
我将编辑问题以包含该信息
完成。 'data' 是 pandas 数据框,data.dtypes 将 data['comment'] 作为对象返回。我认为这应该是瓶颈,因为我只在 Jupyter 单元中执行这些行,而 50mb 大约是 179k 行。
words = " ".join(data["comment"].str.lower()
?但是你真的想要它们成一个巨大的字符串吗?听起来更像是您希望对文档语料库进行标记?
https://pandas.pydata.org/docs/user_guide/text.html#text-string-methods
【参考方案1】:
Pandas 解决方案(比标准库快 2.5 倍)
可以将 Pandas 系列转换为字符串:pandas.Series.str.cat
data = pd.read_csv(file_path)
words = data["comment"].str.cat(sep=' ').lower()
Python 标准库解决方案(较慢)
import csv
comment_list = []
with open(file_path, newline='') as csv_file:
reader = csv.DictReader(csv_file)
for row in reader:
comment_list.append(row["comment"])
words = " ".join(comment_list).lower()
性能测试
使用标准库读取 CSV 与 pandas.read_csv
使用pandas.read_csv()
至少比Python标准库包csv
快2.5倍。
创建一个测试 CSV 文件:test_data.csv
import random
reviews = [
"Love this salad dressing... One my kids will estv😊",
"It’s just soooo delicious but silly price and postage price",
"The sitcome was entertaining but still a waste of time",
"If only I had ten stomaches to enjoy everything the buffet had to offer"
]
with open("test_data.csv", "w") as file:
file.write("random_number,comment,index\n")
for i in range(10000):
file.write(f"random.randint(0, 9),random.choice(reviews),i\n")
读取 CSV 文件 100 次
import csv
import pandas as pd
import timeit
def read_csv_stnd(file_path: str) -> str:
comment_list = []
with open(file_path, newline='') as csv_file:
reader = csv.DictReader(csv_file)
for row in reader:
comment_list.append(row["comment"])
return " ".join(comment_list).lower()
def read_csv_pandas(file_path: str) -> str:
data = pd.read_csv(file_path)
return data["comment"].str.cat(sep=' ').lower()
data_file = "test_data.csv"
print(f"Time to run read_csv_stnd 100 times: timeit.timeit(lambda: read_csv_stnd(data_file), number=100)")
print(f"Time to run read_csv_pandas 100 times: timeit.timeit(lambda: read_csv_pandas(data_file), number=100)")
CSV文件读取结果:
Time to run read_csv_stnd 100 times: 2.349453884999093
Time to run read_csv_pandas 100 times: 0.9676197949993366
标准库 lower()
与 pandas.Series.str.lower
使用标准库函数 lower()
比使用 pandas.Series.str.lower
快大约 5 倍
pandas.Series.str.lower
>>> import pandas as pd
>>> import timeit
>>>
>>> s = pd.Series(['lower', 'CAPITALS', 'this is a sentence', 'SwApCaSe'])
>>> timeit.timeit(lambda: s.str.lower().str.cat(sep=' '), number=10000)
1.9734079910012952
lower()
>>> timeit.timeit(lambda: s.str.cat(sep=' ').lower(), number=10000)
0.3571630870010267
【讨论】:
【参考方案2】:您可以尝试将单词附加到列表中,然后将列表转换为字符串,而不是在每次迭代中创建一个新字符串。也许有类似的东西:
words = [word.lower() for word in data["comment"]]
words = " ".join(words)
我已经用 100,000 个单词对其进行了测试,它似乎比您当前使用的方法快了大约 15 倍。当然,您可以在字符串的开头添加一个空格或进行其他修改以符合您的确切要求。
【讨论】:
【参考方案3】:最明显的改进是连接python字符串如下(这是一种pythonic方式):
words = " ".join((str(msg).lower() for msg in data["comment"]))
您使用的方式会在每次连接时生成新字符串,因为字符串在 python 中是不可变的。
您可以找到更多信息here 或here
【讨论】:
以上是关于连接大型 CSV 文件中单词的最有效方法:pandas 还是 Python 标准库? [复制]的主要内容,如果未能解决你的问题,请参考以下文章
在 Powershell 中,按记录类型拆分大型文本文件的最有效方法是啥?