我对python有点新手 - 并且主要尝试学习python进行数据分析。我有一个看起来像这样的CSV文件(ID,类别):
67512367,0
67567,5
89789789,5
...
...
876289347,10
638, 10
...
...
98723489,20
3828909, 20
...
...<going upto>
78789789, 200
978789, 200
我想要做的是根据类别对ID进行排序。所以,最后我想要一些看起来像这样的东西:
list_5 = [67567, 89789789, .., ]
list_10 = [876289347, 638, ...]
list_200 = [78789789, 978789, ...]
问题是CSV文件有大约150万个条目。所以,我现在使用izip和csv阅读器加载它们,如下所示:
data = izip(csv.reader(open("data.csv", "rb")))
我在data
中有条目,我可以使用它简单地迭代:
for i in data:
print i
#print i[0][0] # for ids
#print i[0][1] # for category
现在,我知道我可以使用if-else / elif构造来检查i[0][1]==5
是否然后将i[0][0]
(ID)附加到列表中,但这似乎非常慢 - 并且我的名单很大。
我想知道是否有任何其他优雅的方式(可能是使用itertools的东西?)来bucketize
基于第二列(类别)的值的ID。
答案 0 :(得分:2)
既然你说你正在尝试学习用于数据分析的python&#34;,你一定要看pandas
,这样你就可以拥有一个更好的工具集。 (当然,并不是说从头开始知道如何构建类似熊猫的工具是没有用的。但根据我的经验,即使有了大熊猫,你也有足够的机会锻炼你的Python技能并且弄清楚如何做一些真实的事情比弄清楚如何重新实现基本功能更有趣。)
您可以使用read_csv
将文件读入DataFrame(如Excel工作表):
>>> import pandas as pd
>>> df = pd.read_csv("group.csv", names=["ID", "category"])
>>> df
ID category
0 67512367 0
1 67567 5
2 89789789 5
3 876289347 10
4 638 10
5 98723489 20
6 3828909 20
7 78789789 200
8 978789 200
然后使用groupby
:
>>> {k: v.tolist() for k,v in df.groupby("category")["ID"]}
{0: [67512367], 200: [78789789, 978789], 10: [876289347, 638], 20: [98723489, 3828909], 5: [67567, 89789789]}
虽然您也可以直接对groupby
个对象进行大量操作(如计算统计等),但说实话,我并不经常需要一个实际的索引列表。更常见的是我只想要&#34;对每个组进行此操作&#34;,但是YMMV。
答案 1 :(得分:0)
您可以使用itertools.groupby:
# test_big.csv was 1.74GB
def test():
from itertools import groupby
bucketized_grouped_keys = {}
with open('test_big','r') as f:
for key, group in groupby(f,lambda T: T.split(',')[1].rstrip('\n')):
bucketized_grouped_keys.update({key:group})
print(bucketized_grouped_keys.keys())
if __name__ == '__main__':
import cProfile
cProfile.run('test()','test.profile')
import pstats
stats = pstats.Stats('test.profile')
stats.strip_dirs().sort_stats('time').print_stats()
输出:
['47', '44', '2', '42', '49']
Thu Aug 07 10:55:39 2014 test.profile
445620949 function calls in 239.002 seconds
Ordered by: internal time
ncalls tottime percall cumtime percall filename:lineno(function)
148540313 95.738 0.000 178.467 0.000 csv_test.py:6(<lambda>)
1 60.535 60.535 239.002 239.002 csv_test.py:2(test)
148540313 55.128 0.000 55.128 0.000 {method 'split' of 'str' objects}
148540313 27.601 0.000 27.601 0.000 {method 'rstrip' of 'str' objects}
1 0.000 0.000 0.000 0.000 {open}
1 0.000 0.000 239.002 239.002 <string>:1(<module>)
5 0.000 0.000 0.000 0.000 {method 'update' of 'dict' objects
}
1 0.000 0.000 0.000 0.000 {method 'keys' of 'dict' objects}
1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Prof
iler' objects}
关键功能是:
lambda T: T.split(',')[1].rstrip('\n')
与:
相同def T(item):
return item.split(',')[1].rstrip('\n')
要访问群组:
category_name = '42'
bucketized_grouped_keys[category_name]
答案 2 :(得分:0)
调用两次排序。
sortedCats = sorted(data, key=attrgetter('category_name'))
sortedIds = sorted(sortedCats, key=attrgetter('id'))
这是有效的,因为python中使用的排序算法是timsort,第二种排序使用第一种排序创建的组来减少工作量。