Извлечение данных из списка с использованием разделителя

#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']