Извлечь информацию между строками из файла и записать в csv

Я хотел бы извлечь некоторую информацию (между строками, например, 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

Не могли бы вы мне помочь? Спасибо.

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
0
82
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Это один из подходов с использованием 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

Ракеш Большое спасибо, но дело в том, что мой набор значений старого и нового времени не всегда идет один за другим, поэтому мне нужно четкое/прямое различие между набором значений старого и нового времени...

Lilly 20.06.2019 15:40

Можете ли вы опубликовать пример и вывод для этого?

Rakesh 20.06.2019 15:44

Например, мой входной файл может выглядеть так: старое время: часы:1:часы!> минуты:12:минуты!> старое время!> старое время: часы:13:часы!> минуты:12:минуты!> старое время!> новое время: часы:11:часы!> минуты:12:минуты!> новое время!>, поэтому мне нужно четкое разделение набора данных, начиная с oldtime: и заканчивая oldtime!>, и набора данных, начиная с newtime: и заканчивая с newtime!>, СПАСИБО

Lilly 20.06.2019 15:55
Ответ принят как подходящий

Другое решение, близкое к решению Ракеша, предполагает, что ваш файл всегда имеет одинаковую структуру (старое время -> час -> мин -> новое время -> час -> мин...).

  1. Извлекать все номера строки с формулой регулярного выражения: match = re.findall(r'\d+', str_file)

  2. Преобразуйте этот список, объединив hours и minutes: dates = [i+ ":" + j for i, j in zip(match[::2], match[1::2])]

  3. Создайте dataframe с помощью модуля pandas

  4. Экспорт данные

Вот код:

# 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 20.06.2019 15:59

@Lilly Редактирование считывает строку файла за строкой и добавляет hours - minutes на основе ключа словаря. Даже если блоки свайпнуты, он все равно работает.

Alexandre B. 20.06.2019 17:22

@ Александр Б. Большое спасибо Александре! «EDIT 1» мне очень помогает. Большое спасибо.

Lilly 20.06.2019 19:30

Рад помочь вам! Ваше здоровье :)

Alexandre B. 20.06.2019 23:03

У вас есть строки типа hours::hours!> или вообще нет строк? Как выглядит ваша проблемная линия?

Alexandre B. 21.06.2019 13:14

Спасибо за ваш ответ. У меня есть, например, несколько пустых строк, например. без очереди час. Итак, моя идея заключалась в том, чтобы каждый раз, когда у меня есть пустая строка для часов, ставить 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] Но это не работает. Не могли бы вы помочь с этим?

Lilly 21.06.2019 13:43

Давайте продолжить обсуждение в чате.

Alexandre B. 21.06.2019 14:06

Хорошо, я иду в чат.

Lilly 21.06.2019 14:13

БОЛЬШОЕ спасибо за помощь Александру Б. Edit 2 работает отлично!

Lilly 21.06.2019 15:45

отличный вопрос :).

Вот простое решение, которое я сделал, расслоив строку на символ «:», превратив числовые строки в целые числа, объединив их с:, а затем записав их в 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.

Lilly 20.06.2019 19:58

Не за что, я понимаю, что даже не ответил на полные вопросы, потому что старое и новое время можно поменять местами... ну да ладно :)

Danny B 20.06.2019 22:06

Другие вопросы по теме