Я пытаюсь разделить большой текстовый файл на более мелкие текстовые файлы. В идеале каждый выходной текстовый файл меньшего размера должен иметь 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'
}
}
Предыдущий вопрос: Поиск определенного ключевого слова при разделении большого CSV-файла на более мелкие сегменты и переход к следующей строке, пока ключевое слово не будет найдено (в настоящее время закрыто)
Честно говоря, панды для этого не нужны. Это просто причиняет тебе проблемы. Просто прочитайте файл как строки и обработайте строки.
Форматирование df0.to_dict() в вашем сообщении (отправленное редактирование) привело к тому, что вы прочитали первую строку как имя столбца, что может привести к потере данных при записи в файл. read_csvесть варианты предотвратить это. См.: "CONTINGENCY 'P11:069:MPW::MPW 7G-G7:NON-BES'" появляется в качестве заголовка столбца в предоставленном вами словаре.
Внимание, нужно ли исключить полученные файлы из glob на случай, если вам придется снова запустить код? Это вернет строки для дублирования копий. Либо сделав glob более конкретным, либо записав Combined.con в отдельную папку.
@OCa Согласен. Если я не исключаю полученные файлы из glob, я не могу сразу запустить повторно, поскольку он добавляет вновь созданные файлы. Спасибо за помощь!






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