6

Переопределение значений в колонке pandas с помощью словаря, сохраняя NaN значения

13

У меня есть словарь, который выглядит так: di = {1: "A", 2: "B"}.

Я хотел бы применить этот словарь к столбцу col1 в DataFrame, который выглядит примерно так:

     col1   col2
0       w      a
1       1      2
2       2    NaN

В результате я хочу получить следующий DataFrame:

     col1   col2
0       w      a
1       A      2
2       B    NaN

Как лучше всего это сделать?

5 ответ(ов)

0

В вашем вопросе есть небольшая неоднозначность. Существует как минимум две интерпретации:

  1. Ключи в di ссылаются на значения индексов.
  2. Ключи в di ссылаются на значения df['col1'].

Ниже приведены решения для каждого случая.


Случай 1: Если ключи в di предназначены для ссылки на значения индексов, то вы можете использовать метод update:

df['col1'].update(pd.Series(di))

Например:

import pandas as pd
import numpy as np

df = pd.DataFrame({'col1':['w', 10, 20],
                   'col2': ['a', 30, np.nan]},
                  index=[1, 2, 0])
#   col1 col2
# 1    w    a
# 2   10   30
# 0   20  NaN

di = {0: "A", 2: "B"}

# Значение по индексу 0 заменяется на 'A', значение по индексу 2 заменяется на 'B'
df['col1'].update(pd.Series(di))
print(df)

результат будет:

  col1 col2
1    w    a
2    B   30
0    A  NaN

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


Случай 2: Если ключи в di ссылаются на значения df['col1'], то вы можете использовать метод replace, как показали @DanAllan и @DSM:

import pandas as pd
import numpy as np

df = pd.DataFrame({'col1':['w', 10, 20],
                   'col2': ['a', 30, np.nan]},
                  index=[1, 2, 0])
print(df)
#   col1 col2
# 1    w    a
# 2   10   30
# 0   20  NaN

di = {10: "A", 20: "B"}

# Значения 10 и 20 заменяются на 'A' и 'B'
df['col1'].replace(di, inplace=True)
print(df)

результат будет:

  col1 col2
1    w    a
2    A   30
0    B  NaN

Обратите внимание, что в этом случае ключи в di были изменены, чтобы соответствовать значениям в df['col1'].


Если у вас есть дополнительные вопросы или требуется уточнение, пожалуйста, дайте знать!

0

При использовании map, который быстрее, чем replace (по решению @JohnE), нужно быть осторожным с неполными отображениями, когда вы собираетесь сопоставлять определенные значения с NaN. В этом случае правильный подход требует, чтобы вы сначала маскировали Series перед вызовом .fillna, иначе вы аннулируете сопоставление с NaN.

Вот пример кода на Python с использованием библиотеки pandas:

import pandas as pd
import numpy as np

d = {'m': 'Male', 'f': 'Female', 'missing': np.NaN}
df = pd.DataFrame({'gender': ['m', 'f', 'missing', 'Male', 'U']})

Здесь мы создаем список ключей, для которых значения являются NaN:

keep_nan = [k for k, v in d.items() if pd.isnull(v)]
s = df['gender']

Затем мы применяем map и корректно обрабатываем NaN:

df['mapped'] = s.map(d).fillna(s.mask(s.isin(keep_nan)))

В результате мы получаем следующий DataFrame:

    gender  mapped
0        m    Male
1        f  Female
2  missing     NaN
3     Male    Male
4        U       U

Таким образом, вы видите, что для элементов, которые отсутствуют в словаре d, и для которых вы хотите, чтобы результат был NaN, правильный подход заключается в использовании маскировки fillna.

0

Вы можете обновить ваш словарь отображений, добавив недостающие пары из DataFrame. Например:

import pandas as pd
import numpy as np

df = pd.DataFrame({'col1': ['a', 'b', 'c', 'd', np.nan]})
map_ = {'a': 'A', 'b': 'B', 'd': np.nan}

# Получаем уникальные значения из df
uniques = df['col1'].unique()
map_new = dict(zip(uniques, uniques))
# {'a': 'a', 'b': 'b', 'c': 'c', 'd': 'd', nan: nan}

# Обновляем отображение
map_new.update(map_)
# {'a': 'A', 'b': 'B', 'c': 'c', 'd': nan, nan: nan}

df['col2'] = df['col1'].map(map_new)

Результат будет следующим:

  col1 col2
0    a    A
1    b    B
2    c    c
3    d  NaN
4  NaN  NaN

Таким образом, вы сможете эффективно расширить ваше отображение, включая новые значения из DataFrame.

0

Если у вас есть более одного столбца, которые необходимо переименовать в DataFrame, вот функция, которая может быть полезна:

def remap(data, dict_labels):
    """
    Эта функция принимает словарь меток: dict_labels 
    и заменяет значения (предварительно закодированные с помощью label encoding) на строки.

    Пример: dict_labels = {'col1': {1: 'A', 2: 'B'}}
    """
    for field, values in dict_labels.items():
        print("Я переименовываю столбец %s" % field)
        data.replace({field: values}, inplace=True)
    print("ГОТОВО")

    return data

Надеюсь, это будет полезно кому-то.

С уважением!

0

Вы можете использовать метод apply для обработки значений в столбце DataFrame следующим образом:

df['col1'].apply(lambda x: {1: "A", 2: "B"}.get(x, x))

Пример использования:

>>> df['col1'] = df['col1'].apply(lambda x: {1: "A", 2: "B"}.get(x, x))
>>> df
  col1 col2
0    w    a
1    1    2
2    2  NaN

В этом примере все значения в столбце col1, которые равны 1 и 2, будут заменены на "A" и "B" соответственно, а остальные значения останутся без изменений.

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь