Извлечение нескольких таблиц / наборов данных из CSV - PullRequest
0 голосов
/ 08 января 2020

У меня есть небольшой CSV-файл, который содержит таблицы / наборы данных не более 50 строк каждая, и каждый разделен пустой строкой. Пример того, как выглядит файл:

Info_header 1
Info_header 2
NaN
Title1, Title2
Column1,Column2,Column3,Column4,Column5,Column6,Column7,Column8
Steve,Indiana,0,0,2,1,2,5
Megan,New York,34,0,0,5,3,2
...
NaN
-Total-,,34,0,2,6,5,7
NaN
Title3,Title4
ColumnA,ColumnB,ColumnC,ColumnD,ColumnE,ColumnF,ColumnG,ColumnH
...

Изменение размера строки и столбца изменяется. Строка с одним NaN представляет собой пустой ряд. Поскольку таблицы имеют имена, l oop, который я планирую использовать, должен начинаться ниже строки с заголовком таблицы:

df = read_csv('data.csv')

start_value = df.loc[(df[0] == "Title1")
                     & (df[1] == "Title2")]

start_value = (start_value.index + 1)

# my loop:

empty_list = []
for index, row in df.loc[start_value[0]].iteritems():
    if pd.isnull(row[1]):
        empty_list.append(df[row])
    else:
        break

Мои логики c - это если встретятся Title1 и Title2 мои критерии, затем добавить строки под строкой заголовка и прекратить добавление, если в строке нет данных. Как я могу это сделать? Я также понимаю, что использование циклов в фреймах данных - не лучшее решение, альтернативные решения приветствуются.

Ответы [ 3 ]

1 голос
/ 09 января 2020

Вот что я бы сделал:

from io import StringIO
import pandas as pd

with open('data.csv') as f:
    block = ''
    for line in f:
        block += line
        if not line[:-1]:
            if len(block.splitlines()) > 3:
                print(pd.read_csv(StringIO(block), skiprows=1))
            block = ''

Результат применительно к данным вашего примера, учитывая, что NaN заменяются пустыми строками, а второй блок завершается некоторыми данными:

#   Column1   Column2  Column3  ...  Column6  Column7  Column8
# 0   Steve   Indiana        0  ...        1        2        5
# 1   Megan  New York       34  ...        5        3        2

# [2 rows x 8 columns]

#    ColumnA  ColumnB  ColumnC  ...  ColumnF  ColumnG  ColumnH
# 0        1        2        3  ...        6        7        8

# [1 rows x 8 columns]
0 голосов
/ 09 января 2020

Содержимое файла данных:

Title 1,Title 2
Column1,Column2,Column3,Column4,Column5,Column6,Column7,Column8
Steve,Indiana,0,0,2,1,2,5
Megan,New York,34,0,0,5,3,2

Title 3,Title 4
ColumnA,ColumnB,ColumnC,ColumnD,ColumnE,ColumnF,ColumnG,ColumnH
val 1 A, val 1 B, val 1 C, val 1 D, val 1 E, val 1 F, val 1 G, val 1 H
val 2 A, val 2 B, val 2 C, val 2 D, val 2 E, val 2 F, val 2 G, val 2 H

Код:

from io import StringIO

import pandas as pd

with open('../resources/temp_in.txt') as in_file:
    file_contents = in_file.read()

tables = []

for curr_str in file_contents.split('\n\n'):
    table_title, table_data = curr_str.split('\n', maxsplit=1)
    table_data = pd.read_csv(StringIO(table_data))
    print(f"{table_title}\n{table_data}\n")
    tables.append((table_title, table_data))

Выход:

Title 1,Title 2
  Column1   Column2  Column3  Column4  Column5  Column6  Column7  Column8
0   Steve   Indiana        0        0        2        1        2        5
1   Megan  New York       34        0        0        5        3        2

Title 3,Title 4
   ColumnA   ColumnB   ColumnC  ...   ColumnF   ColumnG   ColumnH
0  val 1 A   val 1 B   val 1 C  ...   val 1 F   val 1 G   val 1 H
1  val 2 A   val 2 B   val 2 C  ...   val 2 F   val 2 G   val 2 H

[2 rows x 8 columns]
0 голосов
/ 09 января 2020

Если я вас правильно понимаю, вы можете "очистить" свои данные раньше с помощью модуля re (если вы знаете названия заранее).

Например ( Regex101 ):

txt = '''Info_header 1
Info_header 2

Title1, Title2
Column1,Column2,Column3,Column4,Column5,Column6,Column7,Column8
Steve,Indiana,0,0,2,1,2,5
Megan,New York,34,0,0,5,3,2

-Total-,,34,0,2,6,5,7

Title3,Title4
ColumnA,ColumnB,ColumnC,ColumnD,ColumnE,ColumnF,ColumnG,ColumnH
0,1,2,3,4,5,6,7
'''

import re
from io import StringIO

df1 = pd.read_csv( StringIO(re.findall(r'^Title1.*?Title2(.*?)(?:\n\n|\Z)', txt, flags=re.M|re.S)[0]) )
df2 = pd.read_csv( StringIO(re.findall(r'^Title3.*?Title4(.*?)(?:\n\n|\Z)', txt, flags=re.M|re.S)[0]) )

print(df1)
print()
print(df2)

Отпечатки:

  Column1   Column2  Column3  Column4  Column5  Column6  Column7  Column8
0   Steve   Indiana        0        0        2        1        2        5
1   Megan  New York       34        0        0        5        3        2

   ColumnA  ColumnB  ColumnC  ColumnD  ColumnE  ColumnF  ColumnG  ColumnH
0        0        1        2        3        4        5        6        7
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...