Проблема с разделением списка строк на разные столбцы - PullRequest
1 голос
/ 06 августа 2020

Я написал код для извлечения необходимых таблиц из текстовых файлов. Код выглядит следующим образом:

def find_no_line_start_table(table_title,splited_data):
    found_no_lines = []
    for index, line in enumerate(splited_data):
        if table_title in line:
            found_no_lines.append(index)

    return found_no_lines[0]

def get_start_data_table(table_start, splited_data):
    for index, row in enumerate(splited_data[table_start:]):
        if 'TOTAL' in row:
            return table_start + index

def get_end_table(start_table_data, splited_data ):
    for index, row in enumerate(splited_data[start_table_data:]):
            if END_TABLE_LINE in row:
                return start_table_data + index

import requests
import pandas as pd
txt_data = requests.get('https://downloads.usda.library.cornell.edu/usda-esmis/files/3t945q76s/vd66wc47s/sq87c742w/latest.txt'
).text
splited_data = txt_data.split('\n')
table_title = ' U.S. Rice Supply and Use  1/'
END_TABLE_LINE = 'LONG GRAIN RICE'
table_start = find_no_line_start_table(table_title,splited_data)
a = get_start_data_table(table_start, splited_data)
b = get_end_table(a, splited_data)
alpa = splited_data[a:b]
alpa
['TOTAL RICE\r',
 'Area Planted                      2.46          2.95          2.54          2.54\r',
 'Area Harvested                    2.37          2.92          2.48          2.48\r',
 '\r',
 '                                                  Pounds\r',
 'Yield per Harvested Acre          7507          7692          7563          7616\r',
 '\r',
 '                                               Million Hundredweight\r',
 '  Beginning Stocks 2/             46.0          29.4          44.9          44.9\r',
 '  Production                     178.2         224.2         187.3         188.6\r',
 '  Imports                         27.5          29.0          29.6          29.6\r',
...

Есть ли способ преобразовать этот альфа-канал в фрейм данных с 5 разными столбцами, первый из которых является заголовком, а остальные 4 столбца содержат значения. Я пробовал разные методы, такие как str.split, преобразовывая в pd.dataframe. Однако, похоже, ничего не работает. Любые входные данные будут полезны.

@ 0range, что, если в некоторых переменных отсутствует информация.

txt_data = requests.get('https://downloads.usda.library.cornell.edu/usda-esmis/files/3t945q76s/t722h923j/9593tv50h/wasde-05-11-1995.txt').text
splited_data = txt_data.split('\n')
table_title = ' U.S. Rice Supply and Use'
END_TABLE_LINE = 'LONG GRAIN'
table_start = find_no_line_start_table(table_title,splited_data)
a = get_start_data_table(table_start, splited_data)
g = get_end_table(a, splited_data)
alpa = splited_data[a:g] 

Здесь, используя предложенный вами метод словаря, я не могу правильно извлечь последний переменная т.е. цена

1 Ответ

1 голос
/ 07 августа 2020

Итак, чтобы переформулировать ваш вопрос в более общем виде: если я правильно понимаю, вы хотите:

  • преобразовать массив строк в фрейм данных
  • , где строки содержат значения, разделенные несколькими пробелами (по крайней мере, два между каждыми двумя значениями)
  • , так что строки являются столбцами
  • с первым элементом в каждой строке, являющимся столбцом с именем tuple
  • , а остальные элементы (по 4 для каждой строки) являются значениями для строк этого столбца по порядку.

Фреймы данных могут, среди прочего, быть сгенерированы из dicts, где все значения являются списками одинаковой длины ; каждый из них будет преобразован в столбец. Для этого вы можете сначала преобразовать список строк в правильно сформированный dict. Вам также придется немного очистить строки.

Я не буду запускать весь ваш код, а начну со структуры данных, которую вы получили в конце вашего скрипта.

import pandas as pd

""" Example data"""
alpa = ['TOTAL RICE\r',
 'Area Planted                      2.46          2.95          2.54          2.54\r',
 'Area Harvested                    2.37          2.92          2.48          2.48\r',
 '\r',
 '                                                  Pounds\r',
 'Yield per Harvested Acre          7507          7692          7563          7616\r',
 '\r',
 '                                               Million Hundredweight\r',
 '  Beginning Stocks 2/             46.0          29.4          44.9          44.9\r',
 '  Production                     178.2         224.2         187.3         188.6\r',
 '  Imports                         27.5          29.0          29.6          29.6\r']

""" Prepare dict"""
alpadict = {}

""" Parse data"""
for i in range(len(alpa)):
    """ Remove leading and trailing spaces, newlines, etc."""
    alpa[i] = alpa[i].strip()
    
    """ Remove long whitespaces. Only max 2 successive whitespaces remain."""
    while "   " in alpa[i]:
        alpa[i] = alpa[i].replace("   ", "  ")
    
    """ Separate elements"""
    alpa[i] = alpa[i].split("  ")
    
    """ Record into dict (first element as key, others as values in lists)"""
    alpadict[alpa[i][0]] = alpa[i][1:]
    
    """ Add empty elements so that all dict entry lists are of equal length 4"""
    while len(alpadict[alpa[i][0]]) < 4:
        alpadict[alpa[i][0]].append("")
        
""" Transform to dataframe"""
df = pd.DataFrame.from_dict(alpadict)

результат будет:

print(df)

#  TOTAL RICE Area Planted Area Harvested   Pounds Yield per Harvested Acre Million Hundredweight Beginning Stocks 2/ Production Imports
#0                    2.46           2.37                              7507                                      46.0      178.2    27.5
#1                    2.95           2.92                              7692                                      29.4      224.2    29.0
#2                    2.54           2.48                              7563                                      44.9      187.3    29.6
#3                    2.54           2.48                              7616                                      44.9      188.6    29.6

Это то, что вы хотели?

(Как видите, вам, возможно, придется иметь дело с метками, которые охватывают несколько строк, например, «Pounds Yield на убранный акр ".)

Изменить: работа с отсутствующими значениями

В этом случае, я боюсь, вам придется оценивать каждую строку пробелов, если это должен быть только один или два разделителя полей. Учитывая, что в вашем примере значения расположены друг над другом, вы можете работать с фиксированными позициями в строке, чтобы разделить поля. Например:

""" Prepare dict"""
alpadict = {}

""" Parse data"""
for i in range(len(alpa)):
    """ Remove leading and trailing spaces, newlines, etc."""
    alpa[i] = alpa[i].strip()
    
    """ Split strings on particular points."""
    alpa[i] = [alpa[i][:30], alpa[i][30:43], alpa[i][43:57], alpa[i][57:70], alpa[i][70:]]
    
    """ Remove leading and trailing whitespace from all elements"""
    alpa[i] = [a.strip() for a in alpa[i]]
        
    """ Record into dict (first element as key, others as values in lists)"""
    alpadict[alpa[i][0]] = alpa[i][1:]
            
""" Transform to dataframe"""
df = pd.DataFrame.from_dict(alpadict)
...