Python:统计文件中单词出现的次数

4
我是一名有用的助手,可以为您翻译文本。
我有一个文件,每行包含一个城市名称和州名称。我需要统计每个州名称出现的次数并返回结果。
例如,如果我的文件包含以下内容:
Los Angeles   California
San Diego     California
San Francisco California
Albany        New York
Buffalo       New York
Orlando       Florida

我应该返回每个州的名称出现次数。这是加利福尼亚州的代码。

for line in f:
    California_count=line.find("California")
    if California_count!=-1:
        total=line.count("California")
print(total)

我只得到了值 1,我猜想是因为每行只出现一次。如何使它返回数字3而不是数字1?


1
你每次都在覆盖 total 的值。尝试使用 +=(加上并赋值)。顺便说一句,如果你感兴趣的话,这正是 collections.Counter 擅长的地方。 - Two-Bit Alchemist
欢迎来到SO。如果下面的任何一个答案解决了您的问题,您应该接受它(单击适当答案旁边的复选标记)。这样做有两个作用。它让每个人都知道您的问题已经解决,并且它为帮助您的人提供了帮助信用。请参见此处获取完整说明。 - Bruno Gelb
5个回答

7

使用字典来存储计数器:

data = """Los Angeles   California
San Diego     California
San Francisco California
Albany        New York
Buffalo       New York
Orlando       Florida""".splitlines()

counters = {}
for line in data:
    city, state = line[:14], line[14:]
    # city, state = line.split('\t') # if separated by tabulator
    if state not in counters:
        counters[state] = 1
    else:
        counters[state] += 1
print counters
# {'Florida': 1, 'New York': 2, 'California': 3}

您可以通过使用collections.defaultdict来简化它:

from collections import defaultdict
counter = defaultdict(int)
for line in data:
    city, state = line[:14], line[14:]
    counter[state] += 1

print counter
# defaultdict(<type 'int'>, {'Florida': 1, 'New York': 2, 'California': 3})

或者使用collections.Counter和生成器表达式:
from collections import Counter
states = Counter(line[14:] for line in data)
# Counter({'California': 3, 'New York': 2, 'Florida': 1})

4
total = 0

with open('input.txt') as f:
    for line in f:
        found = line.find('California')
        if found != -1 and found != 0:
            total += 1

print total

输出:

3

我认为对于同时包含纽约的两列的行,这不是正确的。 - Mihai Zamfir

3

或者,您可以只使用re模块,并进行正则表达式匹配:

import re

states = """
Los Angeles   California
San Diego     California
San Francisco California
Albany        New York
Buffalo       New York
Orlando       Florida
"""

found = re.findall('[cC]alifornia', states)

total = 0

for i in found:
    total += 1

print total

2

我认为针对这个常见问题的被接受答案已经涵盖了'bw61293'所询问的内容,因为他的文本文件格式的原因,但并不是所有文本文件的通用解决方案!

他要求“计算文件中单词出现的次数”,被接受的答案只能每行计算一次单词“California”。因此,如果该单词在一行中出现两次,则只会计算一次。虽然这对于给定的格式确实有效,但对于一个“文件”是一本书的情况则不是通用解决方案。

以下是对已接受答案的修复,使用nltk将行拆分为单词列表。唯一的问题是确保在命令提示符中使用“pip install nltk”安装nltk库,注意它是一个大型库。如果要使用Anaconda,请使用“conda install -c anaconda nltk”。我使用了Tweet Tokenizer,因为单词中的撇号(例如“don't”)会将字符串拆分成列表['don', "'t"],但TweetTokenizer将返回["don't"],还有其他原因。我还通过在.count()中使用.lower()使其不区分大小写。希望这将有助于那些想要更一般解决“计算文件中单词出现次数”的问题的人们。
我是StackOverflow的新手,请提供反馈以改进我的代码或我第一条评论所写的内容!
更新:我犯了一个错误,现在已经修复!(请记住,这是一个不区分大小写的搜索,如果您想要区分大小写,请从列表推导式中删除.lower()。谢谢。)我也承诺在有足够时间的情况下制作一个不使用nltk的答案。
from nltk.tokenize import TweetTokenizer
tknzr = TweetTokenizer()

total = 0

with open('input.txt') as f:
    for line in f:
        LineList = tknzr.tokenize(line)
        LineLower = [x.lower() for x in LineList]
        found = LineLower.count('california')
        if found != -1 and found != 0:
            total += found

print(total)

1
我认为你提到了接受答案需要改进的原因是很好的,但是在我看来,你的答案有点过头了。你自己提到了 NLTK 是一个庞大的库...请查看由 @m.wasowski 提供的答案,它以更简单的方式解决了这个问题。 - A Merii
1
@AMerii,你说得很对,这确实有些过度了。我会发布更新,并添加一些使用资源不那么密集的库的代码。 - Lachlan Moore

1
假设您帖子中的空格是制表符,以下代码将为您提供一个包含文件中所有州计数的字典。
#!/usr/bin/env python3

counts = {}
with open('states.txt', 'r') as statefile:
    for i in statefile:
        state = i.split('\t')[1].rstrip()
        if state not in counts:
            counts[state] = 0
        else:
            counts[state] += 1
    print(counts)

我认为你的代码给出了错误的最终计数——对于单个实例返回零。将count[state] = 0更改为count[state] = 1 将会修正这个问题。虽然我没有测试过,但我相当确定这个更正是正确的。 - MJM

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接