Как вы сортируете несколько столбцов файла CSV, используя Python? - PullRequest
3 голосов
/ 07 ноября 2011

У меня возникли проблемы с выяснением того, как отсортировать большой набор данных в более полезные данные.

Исходный файл в формате 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.На меньших наборах данных это было просто: лучше отсортировать по X, затем по Y, а затем по энергии, а затем удалить все энергии выше самых низких.Это было достаточно легко для небольших наборов данных, но быстро стало проблематичным.

Я пробовал разные способы сделать это, например, разделить CSV и использовать команду сортировки, но мне немного не повезло.Любые советы о том, как подойти к этому, будут высоко оценены.

Ответы [ 3 ]

3 голосов
/ 07 ноября 2011

Это делает то, что вы просите в своем комментарии к ответу Раймонда - возвращает только строку с самым низким z для каждой пары x, 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]]
2 голосов
/ 07 ноября 2011

После считывания данных в список кортежей с помощью 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')
0 голосов
/ 07 ноября 2011

Я думаю, что numpy's lexsort удовлетворит ваши потребности в сортировке.

В общем, я думаю, что ваши шаги:

  1. Считайте csv в массив numpy- Вы пробовали пакет CSV для Python или функцию genfromtext() numpy * ?

  2. Сортировка с использованием lexsort

  3. Обрезать ненужные строки

РЕДАКТИРОВАТЬ: см. этот связанный вопрос SO .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...