Разделите большой текстовый файл на более мелкие текстовые файлы при обнаружении определенной строки, но с минимальным количеством строк

Я пытаюсь разделить большой текстовый файл на более мелкие текстовые файлы. В идеале каждый выходной текстовый файл меньшего размера должен иметь 5 строк, но если ключевое слово «END» отсутствует в 5-й строке, он должен перейти к следующей строке, пока не найдет ключевое слово «END», а затем создать его как один выходной файл меньшего размера.

Пример входного текстового файла:

CONTINGENCY 'P11:-12.47:DEI:PURDUE CHP GEN'
SET BUS 249831 GENERATION TO 20 MW
END
CONTINGENCY 'P11:-12.47:DEI:PURDUE TG1-2 GENS'
SET BUS 249831 GENERATION TO 15.5 MW
END
CONTINGENCY 'P11:-13.2:DEI:TATE-LYLE BTM GENS'
OPEN BUS 249936
END
CONTINGENCY 'P11:0.342:DEI:08CR_SOL_GEN:1'
REMOVE MACHINE 1 FROM BUS 251904
END

В этом примере 5-я строка (SET BUS 249831 (...)) не имеет ключевого слова «END», поэтому ее следует переместить в 6-ю строку, где есть ключевое слово «END», и создать небольшой текстовый файл из 6 строк, а для следующего шага он должен начинаться с 7-й ряд и повторите тот же процесс.

Соответствующий ожидаемый результат:

# file 1
CONTINGENCY 'P11:-12.47:DEI:PURDUE CHP GEN'
SET BUS 249831 GENERATION TO 20 MW
END
CONTINGENCY 'P11:-12.47:DEI:PURDUE TG1-2 GENS'
SET BUS 249831 GENERATION TO 15.5 MW
END

# file 2
CONTINGENCY 'P11:-13.2:DEI:TATE-LYLE BTM GENS'
OPEN BUS 249936
END
CONTINGENCY 'P11:0.342:DEI:08CR_SOL_GEN:1'
REMOVE MACHINE 1 FROM BUS 251904
END

Мой текущий код создает текстовые файлы меньшего размера, но не выполняет условие «КОНЕЦ»:

import glob
import pandas as pd
import math
import os

if __name__ == "__main__":
    file_dir = os.path.dirname(__file__)
    if file_dir != "":
       os.getcwd()

read_file = glob.glob("*.con")

with open("combined.con", "wb") as outfile:
    for f in read_file:
        with open (f, "rb") as infile:
            outfile.write(infile.read())
        
df0 = pd.read_csv (file_dir + '/combined.con')```
count = len(df0)
row_range = 5
block = count // row_range
for line in df0:
    for i in range(block):   
        if not line.startswith("END"):
            start = i * row_range
            stop = (i+1) * row_range
            while True:
                row_range = row_range + 1
                df2 = df0.iloc[start:stop]
                df2.to_csv(f"Contingency_{i}.con", index=False)
                break

df0.to_dict() (12 первых строк) для воспроизведения рабочего кадра данных:

{"CONTINGENCY 'P11:069:MPW::MPW 7G-G7:NON-BES'": 
 { 0: 'TRIP BRANCH FROM BUS 633408 TO BUS 633007 CKT 1', 
   1: 'REMOVE UNIT 7 FROM BUS 633007', 
   2: 'DISCONNECT BUS 633007', 
   3: 'END', 
   4: "CONTINGENCY 'P11:069:MPW::MPW 8AG-G8A:NON-BES'", 
   5: 'TRIP BRANCH FROM BUS 633408 TO BUS 633018 CKT 1', 
   6: 'REMOVE UNIT A FROM BUS 633018', 
   7: 'DISCONNECT BUS 633018', 
   8: 'END', 
   9: "CONTINGENCY 'P11:069:MPW::MPW 8G-G8:NON-BES'", 
  10: 'TRIP BRANCH FROM BUS 633408 TO BUS 633008 CKT 1', 
  11: 'REMOVE UNIT 8 FROM BUS 633008'
 }
}

Пожалуйста, уточните вашу конкретную проблему или предоставьте дополнительную информацию, чтобы выделить именно то, что вам нужно. Поскольку сейчас написано, трудно точно сказать, о чем вы спрашиваете.

Community 04.06.2024 00:03

Честно говоря, панды для этого не нужны. Это просто причиняет тебе проблемы. Просто прочитайте файл как строки и обработайте строки.

Tim Roberts 04.06.2024 00:54

Форматирование df0.to_dict() в вашем сообщении (отправленное редактирование) привело к тому, что вы прочитали первую строку как имя столбца, что может привести к потере данных при записи в файл. read_csvесть варианты предотвратить это. См.: "CONTINGENCY 'P11:069:MPW::MPW 7G-G7:NON-BES'" появляется в качестве заголовка столбца в предоставленном вами словаре.

OCa 04.06.2024 07:42

Внимание, нужно ли исключить полученные файлы из glob на случай, если вам придется снова запустить код? Это вернет строки для дублирования копий. Либо сделав glob более конкретным, либо записав Combined.con в отдельную папку.

OCa 04.06.2024 07:54

@OCa Согласен. Если я не исключаю полученные файлы из glob, я не могу сразу запустить повторно, поскольку он добавляет вновь созданные файлы. Спасибо за помощь!

Sarvesh Gadre 05.06.2024 18:09
Почему в 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 может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
6
69
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я видел этот вопрос раньше, но он был закрыт до того, как я создал код.

Я не использую панд, не рассчитываю блоки, но Я читаю построчно и добавляю их в список,
и я проверяю, есть ли в списке 5 или более строк и есть ли END в качестве последней строки.
Если в списке есть END и он содержит 5 или более строк, я записываю его в файл и очищаю список.

other_list = []  # list for 5 or more lines
index = 0  # for filename
 
with open("combined.con") as infile:
    for line in infile:
        other_list.append(line)
        if len(other_list) >= 5 and line.startswith('END'):
            with open(f"Contingency_{index}.con", 'w') as outfile:
                for item in other_list:
                    outfile.write(item)
            index += 1
            # clear list
            other_list = []
                   
# make sure there is no data (without `END` in last line)
if len(other_list) > 0:
    with open(f"Contingency_{index}.con", 'w') as outfile:
        for item in other_list:
            outfile.write(item)

Минимальный рабочий код.

Я использую io.StringIO(), чтобы создавать file like object
поэтому я могу поместить примеры данных прямо в код.
И каждый может просто скопировать его для тестов.

import io

other_list = []
index = 0

file_like_obj = io.StringIO("""CONTINGENCY 'P11:-12.47:DEI:PURDUE CHP GEN'
SET BUS 249831 GENERATION TO 20 MW
END
CONTINGENCY 'P11:-12.47:DEI:PURDUE TG1-2 GENS'
SET BUS 249831 GENERATION TO 15.5 MW
END
CONTINGENCY 'P11:-13.2:DEI:TATE-LYLE BTM GENS'
OPEN BUS 249936
END
CONTINGENCY 'P11:0.342:DEI:08CR_SOL_GEN:1'
REMOVE MACHINE 1 FROM BUS 251904
END""")

#with open("combined.con") as infile: 
with file_like_obj as infile:
    for line in infile:
        # skip empty lines
        #if not line.strip():
        #    continue
        other_list.append(line)
        if len(other_list) >= 5 and line.startswith('END'):
            with open(f"Contingency_{index}.con", 'w') as outfile:
                print(f'--- Contingency_{index}.con ---')
                for item in other_list:
                    outfile.write(item)
                    print(item, end='')
            other_list = []
            index += 1
                   
# make sure there is no data (without `END` in last line)
if len(other_list) > 0:
    with open(f"Contingency_{index}.con", 'w') as outfile:
        print(f'--- Contingency_{index}.con ---')
        for item in other_list:
            outfile.write(item)
            print(item, end='')

Результат:

--- Contingency_0.con ---
CONTINGENCY 'P11:-12.47:DEI:PURDUE CHP GEN'
SET BUS 249831 GENERATION TO 20 MW
END
CONTINGENCY 'P11:-12.47:DEI:PURDUE TG1-2 GENS'
SET BUS 249831 GENERATION TO 15.5 MW
END
--- Contingency_1.con ---
CONTINGENCY 'P11:-13.2:DEI:TATE-LYLE BTM GENS'
OPEN BUS 249936
END
CONTINGENCY 'P11:0.342:DEI:08CR_SOL_GEN:1'
REMOVE MACHINE 1 FROM BUS 251904
END

Этот код работает. Большое спасибо за Вашу помощь! Очень ценю это @furas

Sarvesh Gadre 04.06.2024 02:40

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