Переназначение значений в столбце pandas с помощью dict
у меня есть словарь, который выглядит так: 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
как я могу лучше всего это сделать? По какой-то причине термины googling, относящиеся к этому, показывают мне только ссылки о том, как сделать столбцы из диктовок и наоборот :-/
7 ответов:
можно использовать
.replace. Например:>>> df = pd.DataFrame({'col2': {0: 'a', 1: 2, 2: np.nan}, 'col1': {0: 'w', 1: 1, 2: 2}}) >>> di = {1: "A", 2: "B"} >>> df col1 col2 0 w a 1 1 2 2 2 NaN >>> df.replace({"col1": di}) col1 col2 0 w a 1 A 2 2 B NaNили непосредственно в
Series, т. е.df["col1"].replace(di, inplace=True).
mapможет быть намного быстрее, чемreplaceесли ваш словарь имеет более чем пару клавиш, с помощью
mapможет быть намного быстрее, чемreplace. Существует две версии этого подхода, в зависимости от того, исчерпывающе ли ваш словарь отображает все возможные значения (а также Хотите ли вы заменить несоответствия или оставить их как отсутствующие значения):Исчерпывающее Отображение
в этом случае форма очень просто:
df['col1'].map(di) # note: if the dictionary does not exhaustively map all # entries then non-matched entries are changed to NaNsхотя
mapчаще всего принимает функцию в качестве аргумента, он может также принять словарь или ряд:документация для панд.серии.картаНеисчерпывающее Отображение
если у вас есть неисчерпывающее сопоставление и вы хотите сохранить существующие переменные для несоответствий, вы можете добавить
fillna:df['col1'].map(di).fillna(df['col1'])как в ответе @jpp здесь: замените значения в серии панд через словарь эффективно
критерии
используя следующие данные с pandas версии 0.23.1:
di = {1: "A", 2: "B", 3: "C", 4: "D", 5: "E", 6: "F", 7: "G", 8: "H" } df = pd.DataFrame({ 'col1': np.random.choice( range(1,9), 100000 ) })и тестирования с
%timeit, явствует, чтоmap- примерно в 10 раз быстрее, чемreplace.обратите внимание, что ускорение с
mapбудет меняться в зависимости от ваших данных. Самое большое ускорение, по-видимому, связано с большими словарями и исчерпывающими заменами. См. ответ @jpp (связанный выше) для более обширных тестов и обсуждение.
есть немного двусмысленности в вашем вопросе. Есть хотя бы
тридва толкования:
- ключи
diсм. значения Индекса- ключи
diсмотритеdf['col1']значения- ключи
diобратитесь к индексным местоположениям (не вопрос OP, но брошенный для удовольствия.)Ниже приведено решение для каждого случая.
Пример 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"} # The value at the 0-index is mapped to 'A', the value at the 2-index is mapped to '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']значения, затем @DanAllan и @DSM показывают, как достичь этого с помощьюreplace: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"} # The values 10 and 20 are replaced by 'A' and 'B' df['col1'].replace(di, inplace=True) print(df)доходность
col1 col2 1 w a 2 A 30 0 B NaNобратите внимание, как в этом случае ключи в
diбыли изменены, чтобы соответствовать значения indf['col1'].
Случай 3: Если ключи в
diобратитесь к индексным местоположениям, тогда вы можете используйтеdf['col1'].put(di.keys(), di.values())С
df = pd.DataFrame({'col1':['w', 10, 20], 'col2': ['a', 30, np.nan]}, index=[1,2,0]) di = {0: "A", 2: "B"} # The values at the 0 and 2 index locations are replaced by 'A' and 'B' df['col1'].put(di.keys(), di.values()) print(df)доходность
col1 col2 1 A a 2 10 30 0 B NaNздесь первая и третья строки были изменены, потому что ключи в
diare0и2, которые с индексированием на основе 0 Python относятся к первому и третьему местоположениям.
добавление к этому вопросу, если у вас когда-либо было более одного столбца для переназначения в фрейме данных данных:
def remap(data,dict_labels): """ This function take in a dictionnary of labels : dict_labels and replace the values (previously labelencode) into the string. ex: dict_labels = {{'col1':{1:'A',2:'B'}} """ for field,values in dict_labels.items(): print("I am remapping %s"%field) data.replace({field:values},inplace=True) print("DONE") return dataнадеюсь, что это может быть полезным кому-то.
Ура
DSM имеет принятый ответ, но кодирование, похоже, не работает для всех. Вот тот, который работает с текущей версией pandas (0.23.4 по состоянию на 8/2018):
import pandas as pd df = pd.DataFrame({'col1': [1, 2, 2, 3, 1], 'col2': ['negative', 'positive', 'neutral', 'neutral', 'positive']}) conversion_dict = {'negative': -1, 'neutral': 0, 'positive': 1} df['converted_column'] = df['col2'].replace(conversion_dict) print(df.head())вы увидите, что это выглядит так:
col1 col2 converted_column 0 1 negative -1 1 2 positive 1 2 2 neutral 0 3 3 neutral 0 4 1 positive 1документы на панды.Фрейм данных.заменить здесь.
более родной подход панды заключается в применении функции замены, как показано ниже:
def multiple_replace(dict, text): # Create a regular expression from the dictionary keys regex = re.compile("(%s)" % "|".join(map(re.escape, dict.keys()))) # For each match, look-up corresponding value in dictionary return regex.sub(lambda mo: dict[mo.string[mo.start():mo.end()]], text)Как только вы определили функцию, вы можете применить ее к своему фрейму данных.
di = {1: "A", 2: "B"} df['col1'] = df.apply(lambda row: multiple_replace(di, row['col1']), axis=1)
или
apply: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 >>>
Comments