Я хотел бы извлечь некоторую информацию (между строками, например, oldtime: ... oldtime!>) из текстового файла и записать ее в файл CSV. Мой входной текстовый файл выглядит так:
=======================
oldtime:
hours:1:hours!>
minutes:12:minutes!>
oldtime!>
newtime:
hours:15:hours!>
minutes:17:minutes!>
newtime!>
oldtime:
hours:11:hours!>
minutes:22:minutes!>
oldtime!>
newtime:
hours:5:hours!>
minutes:17:minutes!>
newtime!>
==========================
Я начал с этого, но я не могу идти дальше.
with open(inputfile, 'r') as f, open(outputfile.cvs, 'a') as f1:
f1.write("oldtime; newtime \n")
for row in f:
if "oldtime:" in str(row):
temp = re.split(r'(@oldtime[\n\r]|[\n\r]@oldtime!>)', str(row))
???
if "newtime:" in str(row):
temp = re.split(r'(@newtime[\n\r]|[\n\r]@newtime!>)', str(row))
Я хотел бы получить в качестве вывода файл csv, подобный этому
oldtime newtime
01:12 15:17
11:22 05:17
Не могли бы вы мне помочь? Спасибо.
Это один из подходов с использованием Regex и модуля csv
.
Бывший:
import re
import csv
with open(filename) as infile, open(filename_1, "w") as outfile:
data = infile.read()
hrs = re.findall(r"hours:(\d+):hours", data) #Get all HRS
mins = re.findall(r"minutes:(\d+):minutes", data) #Get All Mins
data = zip(hrs, mins)
writer = csv.writer(outfile) #Write CSV
writer.writerow(["oldtime", "newtime"]) #Header
for m, n in zip(data[0::2], data[1::2]):
writer.writerow([":".join(m), ":".join(n)]) #Write OLD time & New Time
Можете ли вы опубликовать пример и вывод для этого?
Например, мой входной файл может выглядеть так: старое время: часы:1:часы!> минуты:12:минуты!> старое время!> старое время: часы:13:часы!> минуты:12:минуты!> старое время!> новое время: часы:11:часы!> минуты:12:минуты!> новое время!>, поэтому мне нужно четкое разделение набора данных, начиная с oldtime: и заканчивая oldtime!>, и набора данных, начиная с newtime: и заканчивая с newtime!>, СПАСИБО
Другое решение, близкое к решению Ракеша, предполагает, что ваш файл всегда имеет одинаковую структуру (старое время -> час -> мин -> новое время -> час -> мин...).
Извлекать все номера строки с формулой регулярного выражения: match = re.findall(r'\d+', str_file)
Преобразуйте этот список, объединив hours
и minutes
: dates = [i+ ":" + j for i, j in zip(match[::2], match[1::2])]
Создайте dataframe
с помощью модуля pandas
Вот код:
# Import module
import pandas as pd
with open("../temp.txt", 'r') as f:
# Read file as a string
str_file = f.read()
# Extract all numbers
match = re.findall(r'\d+', str_file)
print(match)
# ['1', '12', '15', '17', '11', '22', '5', '17']
# create dates
dates = [i+ ":" + j for i, j in zip(match[::2], match[1::2])]
print(dates)
# ['1:12', '15:17', '11:22', '5:17']
# create dataframe
df = pd.DataFrame({"oldtime": dates[::2],
"newtime": dates[1::2]})
print(df)
# oldtime newtime
# 0 1:12 15:17
# 1 11:22 5:17
# Export the data
df.to_csv("output.csv", index= False)
РЕДАКТИРОВАТЬ 1:
Предполагая, что блоки oldtime
и newtime
можно смахнуть. Здесь я читаю файл построчно и классифицирую oldtime
и newtime
в словаре. Их много slice
, но я работаю над своим тестовым файлом.
# Import module
import pandas as pd
with open("../temp.txt", 'r') as f:
# Read file as a string
list_split = ["oldtime:", "newtime:"]
dates = {"oldtime:": [], "newtime:": []}
line = f.readline().rstrip('\n')
while True:
line = line.rstrip('\n')
print([line])
if line in list_split:
key = line
hours = f.readline().rstrip('\n').split(":")[1]
minutes = f.readline().rstrip('\n').split(":")[1]
dates[key].append(hours+':'+minutes)
line = f.readline()
if not line:
break
print(dates)
# {'oldtime:': ['1:12', '11:22'], 'newtime:': ['15:17', '5:17']}
# create dataframe
df = pd.DataFrame({"oldtime": dates["oldtime:"],
"newtime": dates["newtime:"]})
print(df)
# oldtime newtime
# 0 1:12 15:17
# 1 11:22 5:17
# Export the data
df.to_csv("output.csv", index=False)
Обновлено еще раз:
import pandas as pd
with open("../temp.txt", 'r') as f:
# Read file as a string
list_split = ["oldtime:", "newtime:"]
dates = {"oldtime": [], "newtime": []}
line = f.readline().rstrip('\n')
while True:
# Ignore blank lines
if ("oldtime:" in line) or ("newtime:" in line):
# Process new "oldtime" or "newtime" block
# Class : either "oldtime" or "newtime"
class_time = line.replace(" ", "").rstrip('\n')[:-1]
# Default hour - minute values
hours = "24"
minutes = "60"
# Read next line
line = f.readline().rstrip('\n')
# While block not ended
while class_time + "!>" not in line:
# If hour in line: update hour
if 'hour' in line:
hours = line.split(":")[1]
# If minute in line: update minute
elif 'minute' in line:
minutes = line.split(":")[1]
# Read next line
line = f.readline().rstrip('\n')
# End block
# Add block read to dictionary
dates[class_time].append(hours+':'+minutes)
# Read next line
line = f.readline()
# If end of file: exit
if not line:
break
# create dataframe
df = pd.DataFrame({"oldtime": dates["oldtime"],
"newtime": dates["newtime"]})
# Export the data
df.to_csv("output.csv", index=False)
Надеюсь на помощь!
Спасибо, Александр, но дело в том, что мне нужно иметь четкое разделение между наборами данных старого и нового времени, так как это всего лишь пример, и наборы данных могут появляться в другой последовательности. Спасибо.
@Lilly Редактирование считывает строку файла за строкой и добавляет hours
- minutes
на основе ключа словаря. Даже если блоки свайпнуты, он все равно работает.
@ Александр Б. Большое спасибо Александре! «EDIT 1» мне очень помогает. Большое спасибо.
Рад помочь вам! Ваше здоровье :)
У вас есть строки типа hours::hours!>
или вообще нет строк? Как выглядит ваша проблемная линия?
Спасибо за ваш ответ. У меня есть, например, несколько пустых строк, например. без очереди час. Итак, моя идея заключалась в том, чтобы каждый раз, когда у меня есть пустая строка для часов, ставить 24. Поэтому я попытался добавить это в ваш код: temp = f.readline().rstrip('\n').split(":") #print temp if temp[0] == "hours": hours = temp[1] else: hours = 24 минуты = f.readline().rstrip('\n').split(":")[1] Но это не работает. Не могли бы вы помочь с этим?
Давайте продолжить обсуждение в чате.
Хорошо, я иду в чат.
БОЛЬШОЕ спасибо за помощь Александру Б. Edit 2 работает отлично!
отличный вопрос :).
Вот простое решение, которое я сделал, расслоив строку на символ «:», превратив числовые строки в целые числа, объединив их с:, а затем записав их в csv.
Вот код:
import csv
f = "data.txt"
with open('data.txt','r') as f:
data = f.read()
data = data.split(sep=':')
nums = []
for i in data:
try:
nums.append(int(i))
except ValueError:
pass
times = []
for i in range(len(nums)):
if i%2 ==0:
times.append(str(nums[i]) + ":" + str(nums[i+1]))
num_rows = len(times)/2
with open('time_data.csv','w+',newline='') as f:
writer = csv.writer(f)
writer.writerow(['oldtime','newtime'])
for i in range(len(times)):
if i%2==0:
writer.writerow([times[i],times[i+1]])
Прочитав ответ Ракеша, я написал следующее:
import re
import csv
list_i = ''
file_name = 'data.txt'
file_name1 = 'data_1.txt'
with open(file_name,'r') as f, open(file_name1,'w',newline='') as f1:
data = f.read()
list_1 = re.findall(r'hours:\d+:hours',data)
list_2 = re.findall(r'minutes:\d+:minutes',data)
for i in list_1:
list_i += i
list_2_i = ''
for i in list_2:
list_2_i += i
list_1 = re.findall(r'\d+',list_i)
list_2 = re.findall(r'\d+',list_2_i)
data = []
for i in range(len(list_1)):
if i%2==0:
data.append([str(list_1[i]) + ':' + str(list_2[i]),str(list_1[i+1]) + ':' + str(list_2[i+1])])
writer = csv.writer(f1)
writer.writerow(['oldtime','newtime'])
for i in data:
writer.writerow(i)
Также @Rakesh ваш код вернул ошибку: TypeError: объект 'zip' не подлежит подписке Есть ли способ исправить это? :)
Спасибо @DBless. Решение, которое работает для моего случая, принадлежит Alexandre.B.
Не за что, я понимаю, что даже не ответил на полные вопросы, потому что старое и новое время можно поменять местами... ну да ладно :)
Ракеш Большое спасибо, но дело в том, что мой набор значений старого и нового времени не всегда идет один за другим, поэтому мне нужно четкое/прямое различие между набором значений старого и нового времени...