Создать новый столбец, присоединившись к самой таблице несколько раз - PullRequest
1 голос
/ 12 февраля 2020

У меня есть pandas фрейм данных, который содержит список больших членов семьи.

import pandas as pd

data = {'child':['Joe','Anna','Anna','Steffani','Bob','Rea','Dani','Dani','Selma','John','Kevin'],
             'parents':['Steffani','Bob','Steffani','Dani','Selma','Anna','Selma','John','Kevin','-','Robert'],
            }
df = pd.DataFrame(data)

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

child --> parents --> grandparents --> parents of grandparents --> grandparents of grandparents --> etc.

Итак, ожидаемый вывод данных будет выглядеть следующим образом:

    child       parents     A           B           C           D (etc)
---------------------------------------------------------------------------------
0   Joe         Steffani    Dani        Selma       Kevin       <If still possible>
1   Joe         Steffani    Dani        John        -
2   Anna        Bob         Selma       Kevin       Robert
3   Anna        Steffani    Dani        Selma       Kevin
4   Anna        Steffani    Dani        John        -
5   Steffani    Dani        Selma       Kevin       Robert
6   Steffani    Dani        John        -           -
7   Bob         Selma       Kevin       Robert      -
8   Rea         Anna        Bob         Selma       Kevin
9   Rea         Anna        Steffani    Dani        Selma
10  Rea         Anna        Steffani    Dani        John
11  Dani        Selma       Kevin       Robert      -
12  Dani        John        -           -           -
13  Selma       Kevin       Robert      -           -
14  John        -           -           -           -
15  Kevin       Robert      -           -           -

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

Шаг 1

df2 = pd.merge(df, df, left_on='parents', right_on='child', how='left').fillna('-')
df2 = df2[['child_x','parents_x','parents_y']]
df2.columns = ['child','parents','A']

Шаг 2

df3 = pd.merge(df2, df, left_on='A', right_on='child', how='left').fillna('-')
df3 = df3[['child_x','parents_x','A','parents_y']]
df3.columns = ['child','parents','A','B']

Шаг 3

df4 = pd.merge(df3, df, left_on='B', right_on='child', how='left').fillna('-')
df4 = df4[['child_x','parents_x','A','B','parents_y']]
df4.columns = [['child','parents','A','B','C']]

Шаг 4

Напишите аналогичный код, чтобы добавить 6-й столбец для столбца D, если значение в столбце C все еще имеет отношение старшего.

Проблема:

Поскольку у меня большие данные в кадре данных (более 10 Кбайт точек данных), как решить эту проблему без пошагового написания кода? Я не знаю, сколько шагов мне нужно, чтобы составить финальный стол.

Заранее благодарен за любую помощь.

Ответы [ 2 ]

1 голос
/ 12 февраля 2020

Рассмотрим слияние цепей с reduce с использованием суффиксов аргумент merge с некоторой обработкой повторяющихся имен столбцов и удалением промежуточного дочерние столбцы:

def proc_build(x,y):
    temp = (pd.merge(x, y, left_on='parents', right_on='child', 
                     how='left', suffixes=['_',''])                     
              .fillna('-'))

    return temp       

final_df = (reduce(proc_build, [df, df, df, df])
               .set_axis(['child', 'parents',
                          'child1', 'A', 
                          'child2', 'B',
                          'child3', 'C'], axis='columns', inplace=False)
               .reindex(['child', 'parents'] + list('ABC'), axis='columns')
           )

print(final_df)

#        child   parents         A       B       C
# 0        Joe  Steffani      Dani   Selma   Kevin
# 1        Joe  Steffani      Dani    John       -
# 2       Anna       Bob     Selma   Kevin  Robert
# 3       Anna  Steffani      Dani   Selma   Kevin
# 4       Anna  Steffani      Dani    John       -
# 5   Steffani      Dani     Selma   Kevin  Robert
# 6   Steffani      Dani      John       -       -
# 7        Bob     Selma     Kevin  Robert       -
# 8        Rea      Anna       Bob   Selma   Kevin
# 9        Rea      Anna  Steffani    Dani   Selma
# 10       Rea      Anna  Steffani    Dani    John
# 11      Dani     Selma     Kevin  Robert       -
# 12      Dani      John         -       -       -
# 13     Selma     Kevin    Robert       -       -
# 14      John         -         -       -       -
# 15     Kevin    Robert         -       -       -

Чтобы расширить для другого столбца, например D , добавьте еще один df к итерируемый аргумент reduce с дополнительными элементами списка в set_axis и reindex, в частности ['child4', 'D'] и list('ABCD'). Хотя есть способы сделать эти элементы динамичными c, reduce может стоить дорого, и поэтому их следует обрабатывать с некоторым декларативным акцентом.

final_df = (reduce(proc_build, [df] * 5)
               .set_axis(['child', 'parents',
                          'child1', 'A', 
                          'child2', 'B',
                          'child3', 'C',
                          'child4', 'D'], axis='columns', inplace=False)
               .reindex(['child', 'parents'] + list('ABCD'), axis='columns')
           )

print(final_df)

#        child   parents         A       B       C       D
# 0        Joe  Steffani      Dani   Selma   Kevin  Robert
# 1        Joe  Steffani      Dani    John       -       -
# 2       Anna       Bob     Selma   Kevin  Robert       -
# 3       Anna  Steffani      Dani   Selma   Kevin  Robert
# 4       Anna  Steffani      Dani    John       -       -
# 5   Steffani      Dani     Selma   Kevin  Robert       -
# 6   Steffani      Dani      John       -       -       -
# 7        Bob     Selma     Kevin  Robert       -       -
# 8        Rea      Anna       Bob   Selma   Kevin  Robert
# 9        Rea      Anna  Steffani    Dani   Selma   Kevin
# 10       Rea      Anna  Steffani    Dani    John       -
# 11      Dani     Selma     Kevin  Robert       -       -
# 12      Dani      John         -       -       -       -
# 13     Selma     Kevin    Robert       -       -       -
# 14      John         -         -       -       -       -
# 15     Kevin    Robert         -       -       -       -
0 голосов
/ 12 февраля 2020

Это грубое решение от меня. Вы должны оптимизировать его.

  • Загрузка всех файлов данных
  • Сохранить все имена данных в списке
list_data = [data1,data2]
list_df = []
i = 0
for data in list_data:
    vars()[f'df{i}'] = pd.DataFrame(data)
    list_df.append(f'df{i}')
    i += 1
  • Затем создать 2 переменные прокси ;
    • df_family: это будет вывод
    • last_df: для разбиения l oop, в случае, если каждая строка в родительском столбце - '-', но в списке остается кадр данных.
last_df = False
df_family = pd.DataFrame()

  • Эти части будут объединять кадр данных, когда вы будете sh. Я также изменяю имя на 1,2, ..., n, чтобы вы могли легко переименовать его.
for df in list_df:
    if last_df:
        break

    if (eval(df)['parents'] == '-').all():
        last_df = True

    if df_family.empty:
        df_family = eval(df)
    else:
        df_family = pd.merge(df_family,eval(df), how = 'left', left_on = df_family.columns[-1], right_on = eval(df).columns[0])
        df_family.drop(columns = [eval(df).columns[0]], axis = 1, inplace = True)

    list_cols = [i for i in range(df_family.shape[1])]
    df_family.columns = list_cols
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...