文本fi中数据的高效处理

2024-03-29 10:47:40 发布

您现在位置:Python中文网/ 问答频道 /正文

假设我有一个(文本)文件,其结构如下(name,score):

 a         0
 a         1
 b         0
 c         0
 d         3
 b         2

等等。我的目标是把每个名字的分数相加,然后从最高分数到最低分数排序。因此,在本例中,我需要以下输出:

^{pr2}$

事先我不知道档案里会有什么名字。在

我想知道有没有一种有效的方法可以做到这一点。我的文本文件最多可以包含50000个条目。在

我唯一能想到的方法就是从第1行开始,记住那个名字,然后检查整个文件,寻找那个名字和总和。这看起来效率非常低,所以我想知道是否有更好的方法来实现这一点。在


Tags: 文件方法name文本目标排序条目档案
3条回答

熊猫很容易做到这一点:

import pandas as pd
data = pd.read_csv('filename.txt', names=['Name','Score'])
sorted = data.groupby('Name').sum().sort_values('Score', ascending=False)
print sorted

将所有数据读入字典:

from collections import defaultdict
from operator import itemgetter

scores = defaultdict(int)
with open('my_file.txt') as fobj:
    for line in fobj:
        name, score = line.split()
        scores[name] += int(score)

以及排序:

^{pr2}$

印刷品:

d 3
b 2
a 1
c 0

性能

为了检查这个答案与来自@SvenMarnach的答案的性能,我将这两种方法都放入了一个函数中。这里fobj是一个打开供读取的文件。 我使用io.StringIO所以IO延迟应该,希望不是测量的:

from collections import Counter

def counter(fobj):
    scores = Counter()
    fobj.seek(0)
    for line in fobj:
        key, score = line.split()
        scores.update({key: int(score)})
    return scores.most_common()

from collections import defaultdict
from operator import itemgetter

def default(fobj):
    scores = defaultdict(int)
    fobj.seek(0)
    for line in fobj:
        name, score = line.split()
        scores[name] += int(score)
    return sorted(scores.items(), key=itemgetter(1), reverse=True)

collections.Counter的结果:

%timeit counter(fobj)
10000 loops, best of 3: 59.1 µs per loop

collections.defaultdict的结果:

%timeit default(fobj)
10000 loops, best of 3: 15.8 µs per loop

看起来defaultdict快了四倍。我不会猜到的。但说到绩效,你需要衡量。在

这是collections.Counter的一个很好的用例:

from collections import Counter

scores = Counter()
with open('my_file') as f:
    for line in f:
        key, score = line.split()
        scores.update({key: int(score)})

for key, score in scores.most_common():
    print(key, score)

相关问题 更多 >