2017-05-29 211 views
1

我需要导入一个大的.txt文件(大约10GB)来做一些计算。我在Python 2.7中使用熊猫。Python&Pandas。如何在TextFileReader对象中使用“块”的子集?

基本上,我需要根据其他系列的值构造特定系列(列)的总和和平均值。更确切地说:我掌握了居住在一个国家的个人的基本信息,例如,我想要考虑每个城市人们的平均年龄。

我无法导入整个文件(因为它太大了),所以我(使用read_tablechunksize)做的“块”。 对于每个计算,我不需要所有的块,只是它们的一个子集。

由于信息可能无法排序,因此我首先遍历所有区块,以确定其中哪些区域具有每个城市的信息。因此,对于每个城市,我都有一个包含至少包含一个属于它的观察值的块的索引列表。

然后,我想使用此列表来选择只有那些块,但我无法以快速的方式做到这一点。 似乎工作的唯一一件事是再次遍历所有块。

有没有办法直接选择一个TextFileReader对象中的“块”的子集,而无需遍历所有这些“块”?

回答

0

我会尝试做这种方式:

res = \ 
pd.concat([df.assign(age=(pd.datetime.now() - df.dob).astype('m8[Y]').astype(int)) 
      .groupby(['country','municipality'])['age'].agg(['size','sum']).reset_index() 
      for df in pd.read_csv('/path/to/file.txt', sep=..., chunksize=10**5) ], 
      ignore_index=True) 

res = res.groupby(['country','municipality'], as_index=False).sum() 

这会给你个人的总数在每个市(size列)和他们的年龄的总和(sum列)。

sum/size - 会给你一个平均年龄每直辖市

UPDATE:您可以使用下面的技巧,以实时计算年龄:

In [164]: df 
Out[164]: 
    country municipality  dob 
0 Ukraine   m1 1950-01-01 
1 Ukraine   m1 1960-12-14 
2  USA   m2 1971-11-27 
3  USA   m2 1982-11-09 
4  USA   m3 1993-10-22 
5 Germany   m1 2004-10-04 
6 Germany   m2 2015-09-17 

In [165]: df.assign(age=(pd.datetime.now() - df.dob).astype('m8[Y]').astype(int)) 
Out[165]: 
    country municipality  dob age 
0 Ukraine   m1 1950-01-01 67 
1 Ukraine   m1 1960-12-14 56 
2  USA   m2 1971-11-27 45 
3  USA   m2 1982-11-09 34 
4  USA   m3 1993-10-22 23 
5 Germany   m1 2004-10-04 12 
6 Germany   m2 2015-09-17 1 

UPDATE2:pd.read_csv()只要您指定chunksize即可返回pandas.io.parsers.TextFileReader而不是DataFrame

In [6]: reader = pd.read_csv(r'D:\temp\.data\1.csv', chunksize=3, sep='\s+') 

In [7]: type(reader) 
Out[7]: pandas.io.parsers.TextFileReader 

得到2行

In [12]: reader.get_chunk(2) 
Out[12]: 
     foo foo.1 bar bar.1 spam spam.1 
foo 0.00 0.35 0.83 0.84 0.90 0.89 
foo 0.35 0.00 0.86 0.85 0.92 0.91 

获得未来3行

In [13]: reader.get_chunk(3) 
Out[13]: 
     foo foo.1 bar bar.1 spam spam.1 
bar 0.83 0.86 0.00 0.25 0.88 0.87 
bar 0.84 0.85 0.25 0.00 0.82 0.86 
spam 0.90 0.92 0.88 0.82 0.00 0.50 
+0

谢谢你的回答非常@MaxU。我相信这对我在这个问题中给出的具体例子起作用。但是,在某些情况下,我必须在进行计算之前处理数据,并且我想知道是否可以避免每次在所有块上进行迭代。特别是,如果你没有['age']列,而你有['date_of_birth']列,你将如何修改代码?再次感谢! – Vincent

+0

谢谢@MaxU。我仍然不知道是否可以“选择”某些块,但是你的解决方案是好的,而且不需要这样做。如果你碰巧知道,我想如何使用'TextFileReader'对象,因为我显然没有得到它是什么以及它是如何工作的。 – Vincent

+0

@Vincent,请检查最新答案 – MaxU

相关问题