快速排序csv文件?

时间:2014-08-07 15:00:08

标签: python sorting itertools

我对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。

3 个答案:

答案 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

构建类别到ID的字典
>>> {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,第二种排序使用第一种排序创建的组来减少工作量。