跟踪python数据结构中的计数



我有一个大的(~50GB)数据集,其中包含的数据如下:

Group: 1
Attribute 1: 'AAA'
Attribute 2: 3
Group: 1
Attribute 1: 'AAA'
Attribute 2: 3
Group: 1
Attribute 1: 'TTTT'
Attribute 2: 4
Group: 2
Attribute 1: 'GG'
Attribute 2: 2
Group: 2
Attribute 1: 'GG'
Attribute 2: 2

我想在python中编译所有的数据,但我不确定如何设计数据结构。

我的想法是建立一个类似于下面的数据结构。在本例中,添加了数据,但是如果在GroupA1A2中已经存在具有相同数据的行,则只增加Count列,而不是创建另一行。

Group   A1      A2  Count
1       AAA     3   2
1       TTTT    4   1
2       GG      2   2

可以使用标准库collections模块中的namedtuple和Counter。

from collections import namedtuple, Counter
Foo = namedtuple('Foo', ['Group', 'A1', 'A2'])
Counter([
Foo(1, 'AAA', 3),
Foo(1, 'AAA', 3),
Foo(1, 'TTTT', 4),
Foo(2, 'GG', 2),
Foo(2, 'GG', 2),
])

输出:

Counter({Foo(Group=1, A1='AAA', A2=3): 2,
Foo(Group=1, A1='TTTT', A2=4): 1,
Foo(Group=2, A1='GG', A2=2): 2})

这里使用namedtuple的原因是Counter只能处理可哈希值。

如果你构建一个包含整个数据集的列表来传递给Counte,你可能需要大量的RAM。

但是,如果输入数据中有一小组唯一值,则可以使用生成器函数一次处理一个条目。这可以更有效地使用内存,因为您不需要一次将整个数据集加载到内存中。

def lazy_read(filename):
with open(filename) as fp:
for line in fp:
# assuming each line looks like this `1 AAA 3`
group, A1, A2 = line.split()
yield Foo(group, A1, A2)
Counter(lazy_read('foo.data'))

这个lazy_read只是一个最小的例子。有关更详细的生成器函数,请参阅Alex提交的答案。

您很可能需要为这个数据集编写一些自定义解析代码,就像下面的代码片段一样。这将产生每个组及其后面的所有属性,直到下一个组。

def read_dataset(fh):
# Iterate to get first record
for line in fh:
if line.lower().startswith("group"):
name = line.strip()
break
# This list will hold the attribute lines
lines = []
# Now iterate to get attributes
for line in fh:
if line.lower().startswith("group"):
# When in this block we have reached
#  the next record
# yield the previous record's name and
#  attributes
yield name, lines
# Reset the attribute lines and save the
#  name of the next record
lines = []
name = line.strip()
# skip to next line
continue
if line.strip():
lines.append(line.strip())
yield name, lines

然后可以相对容易地遍历该文件,将每个组处理为类似于ha肯的答案的内容。

with open("dataset.txt", "r") as file_handle:
for group, attrs in read_dataset(file_handle):
...
# Process group to get number
# Process attrs 
# Write directly to a CSV or compute counts now

最新更新