#python #string #pandas #list
#python #строка #pandas #Список
Вопрос:
У меня есть набор из 10 списков python в приведенном ниже формате:
[ABC*DEF*123>~123*999*HHH]
[PQR*RST*567>~AWS*999*POI]
[XYZ*TGT*234>~2352*245*HFT]
[STU*DEF*789>~654*345*QQQ]
Я пытаюсь извлечь данные из приведенного выше списка таким образом, чтобы конечным результатом был Dataframe, и ожидаю следующий вывод:
123,999,HHH
AWS,999,POI
2352,245,HFT
654,345,QQQ
Ниже приведено то, что я сделал до сих пор:
allFiles = Path where all the txt files are stored
list_ = []
for file_ in allFiles:
with open(file_) as fp:
lines1 = fp.read().split('n')
b = [i.split('~', 1)[1] for i in lines1]
print(b)
Выше приведен список, как показано ниже:
[123*999*HHH]
[AWS*999*POI]
[2352*245*HFT]
[654*345*QQQ]
Я не могу извлечь вышеуказанные данные с помощью разделителя (*) и разделить их на разные столбцы и сохранить это в Dataframe
Ответ №1:
Вы можете начать с создания фрейма данных со списками строк в виде строк и разделить каждую строку ~
с помощью str.split
. Затем вы можете нарезать результат, выбрав только второй член, за которым следует другое разделение, на этот раз *
, установив expand=True
:
l1 = ['ABC*DEF*123>~123*999*HHH']
l2 = ['PQR*RST*567>~AWS*999*POI']
l3 = ['XYZ*TGT*234>~2352*245*HFT']
l4 = ['STU*DEF*789>~654*345*QQQ']
df = pd.DataFrame([l1,l2,l3,l4], columns=['col1'])
df.col1.str.split('~').str[1].str.split('*', expand=True)
0 1 2
0 123 999 HHH
1 AWS 999 POI
2 2352 245 HFT
3 654 345 QQQ
Обновить
Для выполнения вышеуказанного со списками из нескольких файлов:
l = []
for file_ in allFiles:
f = open(file_, 'r')
l.extend([line.rstrip('n') for line in f.readlines()])
А затем сделайте то же самое, что и раньше:
df = pd.DataFrame(l, columns=['col1'])
df.col1.str.split('~').str[1].str.split('*', expand=True)
Комментарии:
1. спасибо за ответ, однако количество списков не является фиксированным. Он изменяется динамически. Как я мог бы выполнить вышеуказанную работу таким образом, чтобы нам не нужно было определять количество списков.. Спасибо.
2. @scottmartin как сохраняются ваши списки? В большем списке?
3. каждый прочитанный файл сохраняется в виде списка. Как показано в моем первоначальном сообщении, у меня есть ‘n’ списков в результате моего чтения файлов из папки (где n — количество файлов в папке). Надеюсь, я ответил на ваш вопрос здесь.
Ответ №2:
Используйте read_csv
с разделителем ~
и параметром name
s, а затем добавьте Series.str.split
во второй столбец для DataFrame
:
import pandas as pd
temp=u"""ABC*DEF*123>~123*999*HHH
PQR*RST*567>~AWS*999*POI
XYZ*TGT*234>~2352*245*HFT
STU*DEF*789>~654*345*QQQ"""
#after testing replace 'pd.compat.StringIO(temp)' to 'filename.csv'
df = pd.read_csv(pd.compat.StringIO(temp), sep="~", names=['a','b'])
df = df['b'].str.split('*', expand=True)
print (df)
0 1 2
0 123 999 HHH
1 AWS 999 POI
2 2352 245 HFT
3 654 345 QQQ
Если хотите использовать ваше решение, добавьте другое split
:
list_ = []
for file_ in allFiles:
with open(file_) as fp:
lines1 = fp.read().split('n')
b = [i.split('~', 1)[1].split('*') for i in lines1]
list_.append(b)
df = pd.DataFrame([y for x in list_ for y in x])
print(df)
Комментарии:
1. Спасибо. Я добавил еще одну строку, в которой я сохранил список в Dataframe и вижу, что сохраняется только последний список / файл.
df = pd.DataFrame(b)
Не могли бы вы, пожалуйста, помочь. Спасибо.2. @scottmartin — Ты можешь проверить сейчас?
3. просто еще одна справка. У меня есть несколько строк, которые имеют такие значения, как 0001 ~ ABC после выполнения разделения, как упомянуто выше. Не могли бы вы, пожалуйста, посоветовать, как я мог бы изменить приведенный выше код таким образом, чтобы я мог применить этот дополнительный метод разделения (‘~’) к последнему обновленному коду, которым вы поделились выше..
4. @scottmartin — Лучше создать новый вопрос.
Ответ №3:
Поскольку у вас уже есть списки, простая функция может разделить их по разделителю (*).
l1 = ["123*999*HHH"]
l2 = ["AWS*999*POI"]
l3 = ["2352*245*HFT"]
l4 = ["654*345*QQQ"]
def split_delim(l):
for i in l:
l = i.split('*')
return l
l1 = split_delim(l1)
l2 = split_delim(l2)
l3 = split_delim(l3)
df = pd.DataFrame({'l1':l1, 'l2':l2, 'l3':l3})
df
l1 l2 l3
0 123 AWS 2352
1 999 999 245
2 HHH POI HFT
Более обобщенное решение, которое не зависит от количества списков. Это выполняет все операции разделения перед формированием фрейма данных.
#allFiles = Path where all the txt files are stored
def split_delim(Files):
list_ = []
for file_ in Files:
with open(file_) as fp:
lines1 = fp.read().split('n')
b = [i.split('~', 1)[1] for i in lines1]
for i in b:
l = i.split('*')
list_.append(l)
return list_
list_new = split_delim(allFiles)
df = pd.DataFrame(list_new, columns=['col1'])
Ответ №4:
Вы должны явно указать свой разделитель, например
print('ABC*DEF*123>~123*999*HHH'.split('~')[1].split('*'))
производит:
['123', '999', 'HHH']