如何使用python对CSV文件的多个列进行排序?

时间:2011-11-06 21:20:23

标签: python sorting csv import-from-csv

我在解决如何将大型数据集分类为更有用的数据时遇到了问题。

CSV格式的原始文件如下所示 - 数据表示x,y,z位置,最后是能量。 x,y,z坐标在很大程度上分散,这是一个小片段 - 基本上它是一个体积上的能量搜索。

-2.800000,-1.000000,5.470000,-0.26488315
-3.000000,1.000000,4.070000,-0.81185718
-2.800000,-1.000000,3.270000,1.29303723
-2.800000,-0.400000,4.870000,-0.51165026

不幸的是,很难在必要的四维中进行绘图,所以我需要修剪这些数据。我想以这样的方式做到这一点,即我将体积转换为最低能量z轴上的表面。在较小的数据集上,这很简单,在excel中排序X然后是Y然后是能量,然后删除所有能量高于最低值。对于小型数据集来说这很容易,但很快就会出现问题。

我已尝试过各种方法来执行此操作,例如拆分csv和使用sort命令,但我没有运气。任何关于如何处理这个问题的建议都会非常感激。

3 个答案:

答案 0 :(得分:3)

这是您在评论Raymond的答案时所提出的问题 - 只返回每个zx, y的最低行:

from operator import itemgetter
from itertools import groupby
from csv import reader


def min_z(iterable):
    # the data converted from strings to numbers
    floats = [[float(n) for n in row] for row in iterable]
    # the data sorted by x, y, z
    floats.sort(key=lambda (x, y, z, e): (x, y, z))
    # group the data by x, y
    grouped_floats = groupby(floats, key=itemgetter(slice(0, 2)))
    # return the first item from each group
    # because the data is sorted
    # the first item is the smallest z for the x, y group
    return [next(rowgroup) for xy, rowgroup in grouped_floats]


data = """-2.800000,-1.000000,5.470000,-0.26488315
-3.000000,1.000000,4.070000,-0.81185718
-2.800000,-1.000000,3.270000,1.29303723
-2.800000,-0.400000,4.870000,-0.51165026""".splitlines()


print min_z(reader(data))

打印:

[[-3.0, 1.0, 4.07, -0.81185718], 
 [-2.8, -1.0, 3.27, 1.29303723], 
 [-2.8, -0.4, 4.87, -0.51165026]]

答案 1 :(得分:2)

使用csv.reader将数据读入元组列表后,按(x, y)值对数据进行排序。为清楚起见,请使用named tuples标识字段。

然后使用itertools.groupby对相关的(x, y)数据点进行聚类。对于每个组,使用min隔离能量最低的组:

>>> import csv, collections, itertools

>>> raw_data = '''\
-2.800000,-1.000000,5.470000,-0.26488315
-3.000000,1.000000,4.070000,-0.81185718
-2.800000,-1.000000,3.270000,1.29303723
-2.800000,-0.400000,4.870000,-0.51165026
'''.splitlines()

>>> Sample = collections.namedtuple('Sample', ['x', 'y', 'z', 'energy'])
>>> data = [Sample(*row) for row in csv.reader(raw_data)]
>>> data.sort(key=lambda s: (s.x, s.y))
>>> for xy, group in itertools.groupby(data, key=lambda s: (s.x, s.y)):
        print min(group, key=lambda s: s.energy)


Sample(x='-2.800000', y='-0.400000', z='4.870000', energy='-0.51165026')
Sample(x='-2.800000', y='-1.000000', z='5.470000', energy='-0.26488315')
Sample(x='-3.000000', y='1.000000', z='4.070000', energy='-0.81185718')

答案 2 :(得分:0)

我认为numpy的lexsort将满足您的排序需求。

总的来说,我认为您的步骤是:

  1. 将csv读入numpy数组 - 你试过python&#39; s csv package还是numpy&#39; {<3}}?

  2. 使用lexsort排序

  3. 修剪不必要的行

  4. 编辑:见genfromtext() function