#python
#python
Вопрос:
У меня есть несколько CSV-файлов с датой в качестве имени файла (от 20080101.csv до 20111031.csv) в папке. Файлы CSV имеют общие заголовки. CSV-файл выглядит следующим образом:
20080101.csv
X ;Y; Z
1 ; 1 ; 3
1 ; 2 ; 6
1 ; 3 ; 24
2 ; 1 ; 24
2 ; 2 ; 24
20080102.csv
X ;Y; Z
1 ; 1 ; 0.1
1 ; 2 ; 2
1 ; 3 ; 67
2 ; 1 ; 24
2 ; 2 ; 24
20080103.csv
X ;Y; Z
1 ; 1 ; 3
1 ; 3 ; 24
2 ; 1 ; 24
2 ; 2 ; 24
20080104.csv
X ;Y; Z
1 ; 1 ; 34
1 ; 2 ; 23
1 ; 3 ; 67
2 ; 1 ; 24
2 ; 2 ; 24
… и так далее. Я хочу написать скрипт, который будет считывать строки, и если в данной строке у нас есть X = 1 и Y = 2, вся строка копируется в новый файл CSV вместе с именем файла, дающим следующий вывод:
X ;Y ; Z ; filename
1 ; 2 ; 6 ; 20080101
1 ; 2 ; 2 ; 20080102
1 ; 2 ; NA; 20080103
1 ; 2 ; 23; 20080104
Любая идея, как это можно сделать, и любые предложения о модулях, которые я должен изучить, или какие-либо примеры.
Спасибо за ваше время и помощь.
Приветствия, Навин
Комментарии:
1. вас не интересуют записи, чьи (x, y) не являются (1,2)? просто выбросить их?
2. Вы действительно можете назвать файл, разделенный точкой с запятой, csv?
3. @Danny Значения, разделенные символами? С этим я хватаюсь за соломинку 🙂
4. Я видел один, разделенный чертой, почему бы не поставить точку с запятой. кто-нибудь хочет заменить запятую для любой цели, которая у них есть
5. хммм … странное домашнее задание … Чему я могу научиться из этого упражнения?
Ответ №1:
Это правильно сформулированный вопрос, из которого логика должна быть очевидной. Для кого-то предоставление готового кода не соответствовало бы цели назначения. Сначала добавьте к вопросу тег «домашнее задание», затем подумайте о том, что вы хотите сделать: 1) выполните цикл по файлам (отслеживая каждое имя файла по мере его открытия) 2) прочитайте строки из текущего файла 3) если критерии выбора (x == 1 и y == 2) выполнены, затем напишите строку.
Для начала попробуйте:
import csv, os
for fn in os.listdir():
if ".csv" in fn:
with open(fn, 'r', newline='') as f:
reader = csv.reader(f, delimiter=";")
for row in reader:
...
Затем расширьте решение, чтобы открыть выходной файл и записать выбранные строки с помощью csv.writer.
Ответ №2:
Это должно выполнить работу:
import glob
import os
outfile = open('output.csv', 'w')
outfile.write('X ; Y ; Z ; filenamen')
for filename in glob.glob('*.csv'):
if filename == 'output.csv': # Skip the file we're writing.
continue
with open(filename, 'r') as infile:
count = 0
lineno = 0
for line in infile:
lineno = 1
if lineno == 1: # Skip the header line.
continue
fields = line.split(';')
x = int(fields[0])
y = int(fields[1])
z = float(fields[2])
if x == 1 and y == 2:
outfile.write('%d ; %d ; %g ; %sn' % (x, y, z, filename))
count = 1
if count == 0: # Handle the case when no lines were found.
outfile.write('1 ; 2 ; NA ; %sn' % filename)
outfile.close()
Обратите внимание, что если вы не можете контролировать формат файла или доверять ему, вы можете захотеть обрабатывать исключения, возникающие при преобразовании в int / float.
Комментарии:
1. большое вам спасибо … извините за поздний ответ .. будучи новичком, мне потребовалось некоторое время, чтобы понять каждый ценный ответ. Изучать python действительно весело !!
Ответ №3:
Вы могли бы читать в каждом файле одновременно. Прочитайте это построчно
files = ['20080101.csv', '20080102.csv', '20080103.csv'] #...etc
for f in files:
file = open(f, 'r')
for line in file:
ray = line.split(';')
if (ray[0].strip() == '1' and ray[1].strip() == '2'):
fout = open('output.csv', 'a')
fout.write(ray[0].strip() ' ; ' ray[1].strip() ' ; ' ray[2].strip() ' ; ' f 'n')
fout.close()
file.close()
Протестировано и работает. Возможно, потребуются некоторые небольшие изменения.
Комментарии:
1. If всегда завершается ошибкой, поскольку ray является строковым списком.
2. @AdamZalcman: Я проверил этот код, и он работает. ray — это список строк. Я разделяю каждую строку до номера, а затем сравниваю ее с ‘1’ и ‘2’. Пожалуйста, проверьте это и скажите мне, что вы получаете ошибку, прежде чем сообщать мне, что это неправильно.
3. Когда я писал комментарий, вы сравнивали с целыми числами 1 и 2.
4. @AdamZalcman ваш комментарий был написан через 2 минуты после моего последнего редактирования. Но я не буду с вами спорить. Приведенный выше код теперь работает так, как должен.
5. Вы правы, ваша правка была до моего комментария. Я не перезагружал страницу. Кроме того, код действительно работает.
Ответ №4:
если вы знаете, что у вас есть один файл на каждый день, без пропущенных дней, тогда я бы использовал glob (‘*.csv’), чтобы получить список имен файлов, открыть один, пока один, затем прочитать, как это делает Тайлер
если вы знаете, что бывают дни, когда файл отсутствует, я бы использовал datetime для начала с datetime.date (2008,1,1) и увеличивал цикл на один день. затем для каждого дня я составляю имя файла, используя .strftime() ‘.csv’, и пытаюсь обработать файл (если файла нет, просто напишите перекодировку с помощью NA)
Ответ №5:
Должно работать следующее:
import csv
with open('output.csv', 'w') as outfile:
outfile.write('X ; Y ; Z ; filenamen')
fmt = '1 ; 2 ; %s ; %sn'
files = ['20080101.csv', '20080102.csv', '20080103.csv', '20080104.csv']
for file in files:
with open(file) as f:
reader = csv.reader(f, delimiter=';')
for row in reader:
if len(row) > 2 and row[0].strip() == '1' and row[1].strip() == '2':
outfile.write(fmt % (row[2].strip(), file[:-4]))
break
else:
outfile.write(fmt % ('NA', file[:-4]))