Pandas: сопоставить столбец с использованием словаря в нескольких столбцах - PullRequest
1 голос
/ 06 августа 2020

У меня есть фрейм данных со значениями None в одном столбце. Я хотел бы заменить это None значения максимальным значением «категории» для той же комбинации других столбцов.

Пример: pandas dataframe

import pandas as pd
d = {'company': ['Company1', 'Company1', 'Company1', 'Company1', 'Company2', 'Company2'], 'product': ['Product A', 'Product A', 'Product F', 'Product A', 'Product F', 'Product F'], 'category': ['1', None, '3', '2', None, '5']}

df = pd.DataFrame(d)

   company   product       category
0  Company1  Product A        1
1  Company1  Product A     None
2  Company1  Product F        3
3  Company1  Product A        2
4  Company2  Product F     None
5  Company2  Product F        5

Я хочу для замены значений None в 3. столбце значением max () этого столбца для уникальной комбинации (группа 1. + 2. столбец). Ожидаемый результат будет выглядеть так:

   company   product       category
0  Company1  Product A        1
1  Company1  Product A        **2**
2  Company1  Product F        3
3  Company1  Product A        2
4  Company2  Product F        **5**
5  Company2  Product F        5

Что я пробовал: я сгруппировал столбец 1 + 2 («компания + продукт») + получить max () из 3 . column + построить словарь "категория". (на основе идеи GroupBy результатов в словарь списков )

df_dict = df[~df['category'].isna()].groupby(['company','product'])['category'].max().apply(list).to_dict()

, и я получаю этот dict df_dict (показывает максимальное значение категории для каждой комбинации):

{('Company1', 'Product A'): ['2'], ('Company1', 'Product F'): ['1'], ('Company2', 'Product F'): ['5']}

Теперь я хочу заменить None максимальными значениями для каждой комбинации из моего dcitionary

df[df['category'].isna()]

   ompany    product       category
1  Company1  Product A     None
4  Company2  Product F     None

Вопрос, как я могу это сделать? Я пробовал с set_index()

df[df['category'].isna()].set_index(['company', 'product']).index

, в результате получается

MultiIndex([('Company1', 'Product A'),
        ('Company2', 'Product F')],
       names=['company', 'product'])

, который соответствовал бы записи в словаре и использовал ее вместе map()

    df['category'] = df[df['category'].isna()].set_index(['company', 'product']).in
dex.map(df_dict)

... но я получаю ValueError

ValueError: Length of values (2) does not match length of index (6)

1 Ответ

2 голосов
/ 06 августа 2020

два шага,

сначала позволяет превратить эти значения None в NaNs, чтобы мы могли использовать операции numeri c.

df['category'] = pd.to_numeric(df['category']) # add arg ,errors='coerce' if needed.

2-й, позволяет использовать преобразование groupby и max в заполнять только значения NaN.

df["category"] = df["category"].fillna(
    df.groupby(["company", "product"])["category"].transform("max")
)
print(df)

    company    product  category
0  Company1  Product A       1.0
1  Company1  Product A       2.0
2  Company1  Product F       3.0
3  Company1  Product A       2.0
4  Company2  Product F       5.0
5  Company2  Product F       5.0
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...