Замена определенных строк и добавление остальных в файлах CSV с помощью Python - PullRequest
0 голосов
/ 26 июля 2011

У меня есть куча имен файлов, которые мне нужно сложить вместе и вставить в новый файл.Первый столбец - даты.Если даты перекрываются от одного файла к другому, я хочу, чтобы следующий файл, который я добавлял, заменил то, что у меня уже есть.Например, если первый файл имеет вид:

1/5/2010 'hello'
1/6/2010 'goodbye'
1/7/2010 'yes'

, а второй файл:

1/7/2010 'No'
1/8/2010 "spam'
1/9/2010 'today'

Я хочу, чтобы мой новый файл выглядел следующим образом:

1/5/2010 'hello'
1/6/2010 'goodbye'
1/7/2010 'No'
1/8/2010 'spam'
1/9/2010 'today'

Сейчас я пытаюсь что-то вроде этого, но не получаю правильных результатов.(читатель 2 и читатель ссылаются на второй файл и первый файл соответственно, newfile2.csv уже содержит содержимое файла 1)

for row in reader2:
    for row2 in reader:
        if row == row2:
            target = open('newfile2.csv', 'wb')
            writer = csv.writer(target)
            writer.writerow(row)
            target.close()
        else:
            target = open('newfile2.csv', 'ab')
            writer = csv.writer(target)
            writer.writerow(row)
            target.close()

Любые идеи будут высоко оценены.Спасибо, хорошо, поэтому я думаю, что я должен уточнить после прочтения некоторых комментариев.Порядок важен.В конце этого кода, я хочу, чтобы данные за каждый день года были в порядке.Хорошей новостью является то, что данные уже в порядке в файлах, есть только некоторые дубликаты.

Существует более одного дубликата.Например, мой первый файл, с которым я на самом деле имею дело, хранится до 9 марта, а я хочу, чтобы он прекратился в конце февраля.Я хочу получить все данные за март из моего второго файла.

Кроме того, имеется около 1500+ строк, поскольку в реальных файлах каждый час дня также является частью строк.

Надеюсь, это проясняет, что мне нужно сделать.

Я думаю, что может сработать что-то вроде кода, который я выложил выше, но проверить только первый столбец каждой строки (так как только даты будут дублировать друг друга)?Прямо сейчас я проверяю всю строку, и хотя даты являются дубликатами, строки в целом являются уникальными.

О, да, последнее.Я хочу, чтобы все дубликаты были удалены.

Ответы [ 3 ]

1 голос
/ 26 июля 2011

Попробуйте:

dictio = {}
for row in reader:
    [date, text] = row.split()
    dictio[date] = text

for row in reader2:
    [date, text] = row.split()
    dictio[date] = text

target = open('newfile2.csv', 'wb')
writer = csv.writer(target)
for date, text in dictio.iteritems():
    writer.writerow("%s %s" %(date, text))
target.close()

Редактировать : После комментариев, если вы хотите сохранить порядок элементов, измените

dictio = {}

с

dictio = collections.OrderedDict()

это работает для python> 2.6

0 голосов
/ 27 июля 2011

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

Предполагая, что у вас есть список csv readers (в порядке предпочтения - если много файлов содержат строку с одним и тем же ключом, будет взята строка из первого считывателя), csv writer для вывода и функция key для извлечения ключа сортировки для каждой строки, вы можете просто всегда выводить строку, содержащую минимальное значение ключа сортировки, и продвигать все читатели, имеющие одно и то же значение ключа:

def combine(readers, writer, key):
    rows = [reader.next() for reader in readers]
    while rows:
        # select the first input row with the minimum sort key value
        row = min(rows, key=key)
        writer.writerow(row)
        # advance all readers with the minimum sort key value
        min_key = key(row)
        for i in xrange(len(readers)):
            if key(rows[i]) == min_key:
                try:
                    rows[i] = readers[i].next()
                except StopIteration:
                    # reader exhausted, remove it
                    del rows[i]
                    del readers[i]

Чтобы получить сортируемый ключ из файлов примеров, вам нужно проанализировать дату, поскольку она находится в несколько неудобном формате. Использование дат ISO %Y-%m-%d в файлах облегчит жизнь, поскольку они сортируются естественным образом.

import datetime

def key(row):
    return datetime.datetime.strptime(row[0], '%m/%d/%Y')

Соберите все вместе, чтобы вы могли запустить python combine.py input1.csv input2.csv > output.csv. Порядок входных файлов меняется на обратный, так что файлы, указанные позже, переопределяют файлы, указанные ранее.

import csv, sys

delimiter = ' '                         # used in the example input files
readers = [csv.reader(open(filename), delimiter=delimiter)
           for filename in reversed(sys.argv[1:])]
writer = csv.writer(sys.stdout, delimiter=delimiter);
combine(readers, writer, key)
0 голосов
/ 26 июля 2011

Если файлы не очень большие (много тысяч строк), это должно хорошо работать для любого количества входных файлов, поддерживать порядок строк и удалять только дубликаты, как вы указали.

input_files = 'a.csv, b.csv, c.csv, d.csv'

last = '.'
# open the outfile and make the csv writer here
for input_file in input_files:
    # open the infile and make the csv reader here
    lines = reader.readlines()
    # save the last line for later
    last_new = reader.pop()
    if last.split()[0] != lines[0].split()[0]:
        writer.writeln(last)
    writer.writelines(lines)
    last = last_new
    reader.close()
writer.writeln(last)
writer.close()

Если вы хотите избавиться от всех дубликатов, используйте метод dict в одном из других ответов, но не используйте dict, ({}), используйте collections.OrderedDict(), чтобы строки оставайся в порядке.

Альтернативой OrderedDict для Python 2.4-2.6 является http://pypi.python.org/pypi/ordereddict.

...