Присоединиться к 2 датафреймам и создать отношения между родителями и детьми? - PullRequest
0 голосов
/ 04 июля 2018

у меня есть 2 кадра данных: родительский и дочерний, я хочу объединить оба в групповом порядке

df_parent

           parent  parent_value
    0   Super Sun             0
    1  Alpha Mars             4
    2       Pluto             9

df_child

                   child  value
    0         Planet Sun    100
    1  one Sun direction    101
    2     Ice Pluto Tune    101
    3       Life on Mars     99
    4         Mars Robot    105
    5          Sun Twins    200 

Я хочу, чтобы выходной сигнал был в порядке order = ['Sun', 'Pluto', 'Mars']

Sun
-childs
Pluto
-childs
Mards
-childs

Я хочу найти ребенка с ключевым словом, см. parent_dict

parent_dict = {'Super Sun': 'Sun',
           'Alpha Mars': 'Mars',
           'Pluto': 'Pluto'}

ожидаемый результат

    child         value
0   Super Sun             0 # parent
1   Planet Sun          100 # child  
2   one Sun direction   101 # child   
3   Sun Twins           200 # child  
4   Pluto                 9 # parent
5   Ice Pluto Tune      101 # child       
6   Alpha Mars            4 # parent
7   Life on Mars         99 # child    
8   Mars Robot          105 # child    

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

output_df = pd.DataFrame()
for o in order:
    key = o
    for j, row in df_parent.iterrows():
        if key in row[0]:
            output_df.at[j, 'parent'] = key
            output_df.at[j, 'value'] = row[1]
            for k, row1 in df_child.iterrows():
                if key in row1[0]:
                    output_df.at[j, 'parent'] = key
                    output_df.at[j, 'value'] = row[1]              

print(output_df)

Выход:

  parent  value
0    Sun    0.0
2  Pluto    9.0
1   Mars    4.0

Ответы [ 4 ]

0 голосов
/ 04 июля 2018

Рассмотрим объединение обоих фреймов данных и порядка по ключевому слову find:

order = ['Sun', 'Pluto', 'Mars']

def find_keyword(str_param):    
    output = None
    # ITERATE THROUGH LIST AND RETURN MATCHING POSITION
    for i,v in enumerate(order):
        if v in str_param:
            output = i

    return output

# RENAME COLS AND CONCAT DFs
df_combined = pd.concat([df_parent.rename(columns={'parent':'item', 'parent_value':'value'}),
                         df_child.rename(columns={'child':'item'})],
                        ignore_index=True)

# CREATE KEYWORD COL WITH DEFINED FUNCTION
df_combined['keyword'] = df_combined['item'].apply(find_keyword)

# SORT BY KEYWORD AND DROP HELPER COL
df_combined = df_combined.sort_values(['keyword', 'value'])\
                         .drop(columns=['keyword']).reset_index(drop=True)

print(df_combined)
#                 item  value
# 0          Super Sun      0
# 1         Planet Sun    100
# 2  one Sun direction    101
# 3          Sun Twins    200
# 4              Pluto      9
# 5     Ice Pluto Tune    101
# 6         Alpha Mars      4
# 7       Life on Mars     99
# 8         Mars Robot    105
0 голосов
/ 04 июля 2018

Вы можете использовать append с обоими данными после некоторой подготовки. Сначала создайте ключевое слово столбца в df_parent и df_child, используемом для последующей сортировки. Для этого вы используете np.select, например:

import pandas as pd
order = ['Sun', 'Pluto', 'Mars']
condlist_parent = [df_parent['parent'].str.contains(word) for word in order]
df_parent['keyword'] = pd.np.select(condlist = condlist_parent, choicelist = order, default = None)
condlist_child = [df_child['child'].str.contains(word) for word in order]
df_child['keyword'] = pd.np.select(condlist = condlist_child, choicelist = order, default = None)

например, для df_parent:

       parent  parent_value keyword
0   Super Sun             0     Sun
1  Alpha Mars             4    Mars
2       Pluto             9   Pluto

Теперь вы можете использовать append, а также Categorical, чтобы упорядочить фрейм данных в соответствии со списком order. rename используется для соответствия ожидаемому результату и для append, работающего как требуется (столбцы должны иметь одинаковое имя в обоих кадрах данных).

df_all = (df_parent.rename(columns={'parent':'child','parent_value':'value'})
                     .append(df_child,ignore_index=True))
# to order the column keyword with the list order
df_all['keyword'] = pd.Categorical(df_all['keyword'], ordered=True, categories=order)
# now sort_values by the column keyword, reset_index and drop the column keyword
df_output = (df_all.sort_values('keyword')
                  .reset_index(drop=True).drop('keyword',1)) # last two methods are for cosmetic

Выходные данные тогда:

               child  value
0          Super Sun      0
1         Planet Sun    100
2  one Sun direction    101
3          Sun Twins    200
4              Pluto      9
5     Ice Pluto Tune    101
6         Alpha Mars      4
7       Life on Mars     99
8         Mars Robot    105

Примечание. Тот факт, что родители отсортированы по ключевому слову после «потомков», заключается в том, что df_child добавляется к df_parent, а не наоборот.

0 голосов
/ 04 июля 2018

Кажется, это то, что вы хотите:

Сначала создайте столбец kw, чтобы указать , какое ключевое слово соответствует в этой строке

df2['kw'] = [next(iter(s)) for s in df2.child.str.split().transform(set).values & set(parent_dict.values())]
df['kw'] =  [next(iter(s)) for s in df.parent.str.split().transform(set).values & set(parent_dict.values())]

Код кажется сложным, но простым. Вы используете оператор & между одним массивом set s и одним набором ключевых слов. Это позволит извлечь пересечение между каждым набором слов и вашим заранее заданным набором ключевых слов. Часть next(iter(s)) - это просто быстрый способ получить первый элемент из set. (Я предполагаю, что в каждой строке будет присутствовать только одно ключевое слово. Если вы хотите дифференцировать строки по количеству найденных ключевых слов - например, классифицировать строку только с «Марсом» и строку с «Марсом» "и" Плутон "должны отличаться - тогда вы должны использовать tuple(s) и использовать кортежи, которые можно хэшировать)

Затем вы можете назначить категории для каждого df, чтобы помочь вам позже

df['cat'] = 'parent'
df2['cat'] = 'child'

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

pd.concat([df,df2.rename(columns={'child':'parent', 'value':'parent_value'})],sort=False).set_index(['kw', 'cat']).sort_index(ascending=[True,False])

                parent              parent_value
kw      cat     
Mars    parent  Alpha Mars          4
        child   Life on Mars        99
        child   Mars Robot          105
Pluto   parent  Pluto               9
        child   Ice Pluto Tune      101
Sun     parent  Super Sun           0
        child   Planet Sun          100
        child   one Sun direction   101
        child   Sun Twins           200

Обратите внимание, что я переименовал столбцы, чтобы они были такими же, как parent_df. Вы можете выбрать любое имя, которое вам подходит. Если вы хотите точно опубликованный вами результат, просто сбросьте индекс после сортировки и извлеките два последних столбца:

(....).reset_index()[['parent', 'parent_value']]

    parent              parent_value
0   Alpha Mars          4
1   Life on Mars        99
2   Mars Robot          105
3   Pluto               9
4   Ice Pluto Tune      101
5   Super Sun           0
6   Planet Sun          100
7   one Sun direction   101
8   Sun Twins           200
0 голосов
/ 04 июля 2018

Вот одно из решений, итерирующее оба фрейма данных, но эта процедура кажется очень и очень длинной

output_df = pd.DataFrame()
c = 0
for o in order:
    key = o
    for j, row in df_parent.iterrows():
        if key in row[0]:
            output_df.at[c, 'parent'] = row[0]
            output_df.at[c, 'value'] = row[1]
            c += 1
            for k, row1 in df_child.iterrows():
                if key in row1[0]:
                    output_df.at[c, 'parent'] = row1[0]
                    output_df.at[c, 'value'] = row1[1]              
                    c += 1

Выход:

              parent  value
0          Super Sun    0.0
1         Planet Sun  100.0
2  one Sun direction  101.0
3          Sun Twins  200.0
4              Pluto    9.0
5     Ice Pluto Tune  101.0
6         Alpha Mars    4.0
7       Life on Mars   99.0
8         Mars Robot  105.0
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...