синтаксический анализ CSV в кадры данных pandas (разблокировка «один ко многим»)

У меня есть файл csv, импортированный в кадр данных pandas. Вероятно, это произошло из-за экспорта базы данных, в котором объединены родительская и подробная таблицы «один ко многим». Формат CSV-файла следующий:

header1, header2, header3, header4, header5, header6

sample1, property1,,,average1,average2
,,detail1,detail2,,
,,detail1,detail2,,
,,detail1,detail2,,

sample2, ...
,,detail1,detail2,,
,,detail1,detail2,,
...

(т. е. line 0 — это header, line 1 — это record 1, с lines 2 по n — детали, строка n+1 — это запись 2 и т. д....)

Каков наилучший способ выделить (перенормировать?) детали в отдельные DataFrames, на которые можно ссылаться, используя значения в sample# записях? Количество каждого подмножества деталей различно для каждого образца.

Я могу использовать:

samplelist = df.header2[pd.notnull(df.header2)]

чтобы получить начальный индекс каждого образца, чтобы я мог получить от samplelist.index[0] до samplelist.index[1] и поместить его в меньший фрейм данных. Подробные записи сами по себе не имеют ссылки на образец, из которого они были получены, поэтому это должно быть выведено из порядка файла csv (обратите внимание, что в моем примере нет пересечения заполненных/пустых полей).

Должен ли я составить список фреймов данных, список фреймов данных или панель фреймов данных?

Могу ли я каким-то образом создать переменные из полей записи sample1 и каким-то образом прикрепить их к каждому фрейму данных, который имеет только подробные записи (например, набор объектов, которые имеют несколько скалярных членов и один фрейм данных каждый)?

В конце концов я создам статистику по данным из каждой группы подробных записей и нанесу их на график относительно значений в выборочных записях (например, тип выборки, день или дата и т. д. по сравнению с моей статистикой). Я создам промежуточные ряды, которые также будут прикреплены к группе образцов, например PDF-файл оценки плотности ядра или гистограмма.

Спасибо.


person Community    schedule 14.06.2016    source источник


Ответы (2)


Вы можете использовать тот факт, что первая column кажется пустой, если только это не новая запись sample для .fillna(method='ffill'), а затем .groupby('header1') чтобы получить все отдельные группы. По ним можно сразу считать статистику или хранить как отдельные DataFrame. Эскиз высокого уровня выглядит следующим образом:

df.header1 = df.header1.fillna(method='ffill')
for sample, data in df.groupby('header1'):
     print(sample) # access to sample name
     data = ... # process sample records
person Stefan    schedule 14.06.2016
comment
Ваш пример позволяет мне легко получить мои данные. Форвардное заполнение было очень полезным. У меня работает ваш пример, только теперь каждый проход цикла for должен сохранять sample и data в какой-то новый объект. Я надеялся на два новых фрейма данных. Это просто потому, что я привык думать о таблицах SQL. Я все еще ломаю голову над тем, как эффективно использовать объект groupby. - person ; 07.07.2016

Ответ выше заставил меня двигаться в правильном направлении. При дальнейшей работе использовалось следующее. Оказывается, мне нужно было использовать два столбца в качестве составного ключа для уникальной идентификации образцов.

df.header1 = df.header1.fillna(method='ffill')
df.header2 = df.header2.fillna(method='ffill')

grouped = df.groupby(['header1','header2'])

samplelist = []
dfParent = pd.DataFrame()
dfDetail = pd.DataFrame()

for sample, data in grouped:
    samplelist.append(sample)
    dfParent = dfParent.append(grouped.get_group(sample).head(n=1), ignore_index=True)
    dfDetail = dfDetail.append(data[1:], ignore_index=True)

dfParent = dfParent.drop(['header3','header4',etc...]) # remove columns only used in 
                                                       # detail records
dfDetail = dfDetail.drop(['header5','header6',etc...]) # remove columns only used once
                                                       # per sample

# Now details can be extracted by sample number in the sample list 
# (e.g. the first 10 for sample 0)

samplenumber = 0

dfDetail[
    (dfDetail['header1'] == samplelist[samplenumber][0]) &
    (dfDetail['header2'] == samplelist[samplenumber][1])
    ].header3[:10]

Полезными ссылками были:

Pandas groupby и get_group

Pandas добавляются к DataFrame

person Community    schedule 07.07.2016