Сортировка CSV в Python - PullRequest
       13

Сортировка CSV в Python

6 голосов
/ 18 января 2010

Я предполагал, что сортировка файла CSV по нескольким текстовым / числовым полям с использованием Python будет проблемой, которая уже решена. Но я нигде не могу найти ни одного примера кода, за исключением конкретного кода, фокусирующегося на полях даты сортировки.

Как можно отсортировать относительно большой CSV-файл (десятки тысяч строк) по нескольким полям по порядку?

Примеры кода Python приветствуются.

Ответы [ 4 ]

10 голосов
/ 18 января 2010

Сортировка Python работает только в памяти;однако десятки тысяч строк должны легко помещаться в памяти на современном компьютере.Итак:

import csv

def sortcsvbymanyfields(csvfilename, themanyfieldscolumnnumbers):
  with open(csvfilename, 'rb') as f:
    readit = csv.reader(f)
    thedata = list(readit)
  thedata.sort(key=operator.itemgetter(*themanyfieldscolumnnumbers))
  with open(csvfilename, 'wb') as f:
    writeit = csv.writer(f)
    writeit.writerows(thedata)
4 голосов
/ 19 января 2010

Вот ответ Алекса, переработанный для поддержки типов данных столбца:

import csv
import operator

def sort_csv(csv_filename, types, sort_key_columns):
    """sort (and rewrite) a csv file.
    types:  data types (conversion functions) for each column in the file
    sort_key_columns: column numbers of columns to sort by"""
    data = []
    with open(csv_filename, 'rb') as f:
        for row in csv.reader(f):
            data.append(convert(types, row))
    data.sort(key=operator.itemgetter(*sort_key_columns))
    with open(csv_filename, 'wb') as f:
        csv.writer(f).writerows(data)

Edit:

Я сделал глупость. Я играл с различными вещами в IDLE и написал функцию convert пару дней назад. Я забыл, что написал это, и долго не закрывал IDLE - поэтому, когда я писал выше, я думал, что convert - встроенная функция К сожалению, нет.

Вот моя реализация, хотя у Джона Макина лучше:

def convert(types, values):
    return [t(v) for t, v in zip(types, values)]

Использование:

import datetime
def date(s):
    return datetime.strptime(s, '%m/%d/%y')

>>> convert((int, date, str), ('1', '2/15/09', 'z'))
[1, datetime.datetime(2009, 2, 15, 0, 0), 'z']
2 голосов
/ 19 января 2010

Вот convert(), которого не хватает в ответе Роберта на ответ Алекса:

>>> def convert(convert_funcs, seq):
...    return [
...        item if func is None else func(item)
...        for func, item in zip(convert_funcs, seq)
...        ]
...
>>> convert(
...     (None, float, lambda x: x.strip().lower()),
...     [" text ", "123.45", " TEXT "]
...     )
[' text ', 123.45, 'text']
>>>

Я изменил имя первого аргумента, чтобы подчеркнуть, что функция для каждого столбца может делать то, что вам нужно, а не просто приведение типов. None используется для обозначения отсутствия преобразования.

0 голосов
/ 18 января 2010

Вы поднимаете 3 вопроса:

  • размер файла
  • данные CSV
  • сортировка по нескольким полям

Вот решение для третьей части. Вы можете обрабатывать данные CSV более сложным способом.

>>> data = 'a,b,c\nb,b,a\nb,c,a\n'
>>> lines = [e.split(',') for e in data.strip().split('\n')]
>>> lines
[['a', 'b', 'c'], ['b', 'b', 'a'], ['b', 'c', 'a']]
>>> def f(e):
...     field_order = [2,1]
...     return [e[i] for i in field_order]
... 
>>> sorted(lines, key=f)
[['b', 'b', 'a'], ['b', 'c', 'a'], ['a', 'b', 'c']]

Отредактировано для использования понимания списка, генератор не работает так, как я ожидал.

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