3

我在弄清楚如何将大型数据集分类为更有用的数据时遇到问题。

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 命令,但我运气不佳。任何有关如何解决此问题的建议将不胜感激。

4

3 回答 3

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]]
于 2011-11-06T23:37:10.023 回答
2

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

然后使用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')
于 2011-11-06T21:32:05.003 回答
0

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

一般来说,我认为你的步骤是:

  1. 将 csv 读入 numpy 数组——你试过 python 的csv 包或 numpy 的genfromtext()函数吗?

  2. 使用 lexsort 进行排序

  3. 修剪不必要的行

编辑:请参阅这个相关的 SO 问题

于 2011-11-06T21:27:30.607 回答