У меня есть словарь, который выглядит так: di = {1: "A", 2: "B"}
Я хотел бы применить его к столбцу "col1" в кадре данных, похожем на:
col1 col2
0 w a
1 1 2
2 2 NaN
получить:
col1 col2
0 w a
1 A 2
2 B NaN
Как я могу лучше всего это сделать? По некоторым причинам термины поиска в Google, относящиеся к этому, показывают только ссылки о том, как сделать столбцы из разногласий и наоборот: - /
python
dictionary
pandas
remap
TheChymera
источник
источник
col```` is tuple. The error info is
не удается сравнить типы 'ndarray (dtype = object)' и 'tuple'```'3.6.1 |Anaconda custom (64-bit)| (default, May 11 2017, 13:25:24) [MSC v.1900 64 bit (AMD64)]'
map
может быть намного быстрее, чемreplace
Если ваш словарь содержит более пары ключей, использование
map
может быть намного быстрее, чемreplace
. Существует две версии этого подхода, в зависимости от того, исчерпывающе ли сопоставляет ваш словарь все возможные значения (а также от того, хотите ли вы, чтобы несоответствия сохранили свои значения или были преобразованы в NaN):Исчерпывающее картографирование
В этом случае форма очень проста:
Хотя
map
чаще всего в качестве аргумента используется функция, в качестве альтернативы можно использовать словарь или серию: Документация для Pandas.series.mapНеисчерпывающее картографирование
Если у вас есть неполное сопоставление и вы хотите сохранить существующие переменные для несоответствий, вы можете добавить
fillna
:как в ответе @ jpp здесь: Замените значения в ряду панд через словарь эффективно
Ориентиры
Используя следующие данные с версией панды 0.23.1:
и тестирование
%timeit
, кажется,map
примерно в 10 раз быстрее, чемreplace
.Обратите внимание, что ваше ускорение
map
зависит от ваших данных. Наибольшее ускорение, по-видимому, связано с большими словарями и исчерпывающими заменами. Посмотрите ответ @jpp (ссылка выше) для более подробных тестов и обсуждения.источник
df.replace
Функции, в то время как аккуратные и полезно для маленькой dicts, разбились после запуска в течение 20 минут или около того .map
также работает над индексом, где я не мог найти способ сделать этоreplace
В вашем вопросе есть немного неясности. Существует как минимум
тридве интерпретации:di
относятся к значениям индексаdi
относятся кdf['col1']
значениямdi
относятся к указателям (не вопрос ОП, но добавлены для забавы).Ниже приведено решение для каждого случая.
Случай 1: если ключи
di
предназначены для ссылки на значения индекса, то вы можете использоватьupdate
метод:Например,
доходность
Я изменил значения из вашего исходного поста, чтобы было понятнее, что
update
происходит. Обратите внимание, как ключиdi
связаны со значениями индекса. Порядок значений индекса, то есть местоположения индекса, не имеет значения.Случай 2: если ключи
di
относятся кdf['col1']
значениям, то @DanAllan и @DSM показывают, как этого добиться с помощьюreplace
:доходность
Обратите внимание, как в этом случае ключи
di
были изменены, чтобы соответствовать значениям вdf['col1']
.Случай 3: если ключи
di
относятся к указателям, то вы можете использоватьпоскольку
доходность
Здесь первые и третьи ряды были изменены, потому что ключи в
di
это0
и2
, которые при индексации на основе 0 Пайтона относятся к первым и третьим местам.источник
replace
одинаково хорошо, и, возможно, лучшее слово для того, что здесь происходит.update()
кажется немного глупым по сравнению сreplace()
, но по крайней мере это работает.Добавим к этому вопросу, если у вас когда-либо будет более одного столбца для переназначения в кадре данных:
Надеюсь, что это может быть полезно для кого-то.
ура
источник
DataFrame.replace()
, хотя я не знаю, когда она была добавлена.У DSM есть принятый ответ, но кодирование, кажется, не работает для всех. Вот тот, который работает с текущей версией панд (0.23.4 от 8/2018):
Вы увидите, что это выглядит так:
Документы для панд. DataFrame.replace здесь .
источник
Series.map()
кажется более гибким.Или сделать
apply
:Демо-версия:
источник
di
диктат является списком? Как вы можете отобразить только одно значение в списке?Учитывая, что
map
это быстрее, чем заменить (решение @ JohnE), вы должны быть осторожны с неисчерпывающими отображениями, в которые вы намереваетесь отобразить конкретные значенияNaN
. Правильный метод в этом случае требует, чтобы выmask
использовали Серию, когда вы.fillna
, иначе вы отмените сопоставлениеNaN
.источник
Хорошее законченное решение, которое хранит карту меток ваших классов:
Таким образом, вы можете в любой момент обратиться к исходной метке класса из label_dict.
источник
В качестве дополнения к тому, что было предложено Nico Coallier (применимо к нескольким столбцам) и U10-Forward (с использованием методов применения стиля), и обобщив его в виде однострочника, я предлагаю:
.transform()
Обрабатывает каждый столбец в виде ряда. В отличие от.apply()
чего передаются столбцы, агрегированные в DataFrame.Следовательно, вы можете применить метод серии
map()
.Наконец, и я обнаружил это поведение благодаря U10, вы можете использовать всю серию в выражении .get (). Если только я неправильно понял его поведение и он последовательно обрабатывает серию, а не поразрядно.
На
.get(x,x)
счетах для значений, не говоря уже в словаре отображения , которое будет рассматриваться как Nan иного.map()
методомисточник
.transform()
Обрабатывает каждый столбец в виде ряда. В отличие от.apply()
чего передаются столбцы, агрегированные в DataFrame. Я только что попробовал,apply()
работает отлично. Там нет необходимости использоватьloc
, это кажется слишком сложным.df[["col1", "col2"]].apply(lambda col: col.map(lambda elem: my_dict.get(elem, elem)))
должно работать просто отлично. На.get(x,x)
счетах для значений, не говоря уже в словаре отображения , которое будет рассматриваться как Nan иного.map()
способом Вы могли бы также использоватьfillna()
впоследствии.Более родной подход панд заключается в применении функции замены, как показано ниже:
После того как вы определили функцию, вы можете применить ее к вашему фрейму данных.
источник