Как я могу присвоить значение столбца на основе общих элементов списка между 2 фреймами данных

#python #pandas #dataframe

#python #pandas #фрейм данных

Вопрос:

У меня есть два фрейма данных.

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

 df1 = pd.DataFrame([['a', ['Elementary', 'Pre Schools', 'High Schools'], None], ['b', ['Museums'], None], ['c', ['Junior High Schools', 'Military - Misc.', 'Roads', 'Sewers and Water Mains'], None]], columns=['Record Name', 'Terms', 'Industry'])
  

df1 выглядит так

   Record Name  Terms                                                                  Industry
0   a          [Elementary, Pre Schools, High Schools]                                  None
1   b          [Museums]                                                                None
2   c          [Junior High Schools, Military - Misc., Roads, Sewers and Water Mains]   None
  

Второй df предоставляет списки терминов и их соответствующую «отрасль».

 df2 = pd.DataFrame([['Arts', ['Libraries', 'Museums', 'Auditoriums', 'Entertainment']], ['Education', ['Elementary', 'Pre Schools', 'College', 'University', 'Junior High Schools', 'High Schools']]])
  

d2 выглядит так

     Industry                        Terms
0   Arts                            [Libraries, Museums, Auditoriums, Entertainment]
1   Education                       [Elementary, Pre Schools, College, University, Junior High Schools, High Schools]
  

df2 содержит 10 различных отраслей с примерно 100 терминами, распределенными по ним. Не каждый термин, присутствующий в df1, используется для классификации отрасли в df2.

Как бы я назначил «отраслевые» значения в df1 на основе любых общих элементов списка «терминов» между df1 и df2? Вот желаемый результат:

       Record Name  Terms                                                                  Industry
    0   a          [Elementary, Pre Schools, High Schools]                                  Education
    1   b          [Museums]                                                                Arts
    2   c          [Junior High Schools, Military - Misc., Roads, Sewers and Water Mains]   Education 
  

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

 df1.loc[df1['Terms'].isin(Education), 'Industry'] = 'Education'
  

Но это присваивает «Отрасль» только для записей, все их «термины» присутствуют в списке образования. Кроме того, поскольку существует 10 различных отраслей, определение списков и создание отдельных назначений для каждого из них было бы громоздким. Я считаю, что оценка общих «терминов» между двумя фреймами данных была бы более чистым подходом.

Комментарии:

1. В вашем столбце df1 есть несколько элементов Terms . Какому из них оно должно соответствовать?

2. Любой df1 [‘Terms’], общий для df2 [‘Terms’], должен быть сопоставлен.

Ответ №1:

Мне сложно работать со списками в фреймах данных, поэтому я сначала разбиваю списки, затем объединяю фреймы данных и собираю списки вместе.

 #This just helps me keep the columns straight
df2.columns = ['Industry', 'Terms']

# Drop Industry in df1 and explode the lists in df1 amp; df2
df1 = df1.drop('Industry', axis=1).explode('Terms')
df2 = df2.explode('Terms')

# Merge the terms back into df1
df1 = df1.merge(df2, how='left', on='Terms')

# Bring the lists back together
df1 = df1.groupby('Record Name').agg(lambda x: x.dropna().unique().tolist())
  

Результат:

                                                          Terms     Industry
Record Name                                                                
a                      [Elementary, Pre Schools, High Schools]  [Education]
b                                                    [Museums]       [Arts]
c            [Junior High Schools, Military - Misc., Roads,...  [Education]