Изменение одного значения на основе другого значения в панд
Я пытаюсь перепрограммировать свой код Stata в Python для улучшения скорости, и мне указали в направлении панд. Тем не менее, мне трудно обернуть голову вокруг того, как обрабатывать данные.
допустим, я хочу перебрать все значения в заголовке столбца 'ID."Если этот идентификатор соответствует определенному номеру, то я хочу изменить два соответствующих значения FirstName и LastName.
в Stata это выглядит так:
replace FirstName = "Matt" if ID==103
replace LastName = "Jones" if ID==103
Так это заменяет все значения в FirstName, которые соответствуют значениям ID == 103 на Matt.
в панд, я пытаюсь что-то вроде этого
df = read_csv("test.csv")
for i in df['ID']:
if i ==103:
...
Не уверен, куда идти отсюда. Есть идеи?
4 ответа:
один из вариантов-использовать функции нарезки и индексирования Python для логической оценки мест, где ваше условие удерживает и перезаписывает данные там.
предполагая, что вы можете загрузить свои данные непосредственно в
pandas
Сpandas.read_csv
тогда следующий код может быть полезен для вас.import pandas df = pandas.read_csv("test.csv") df.loc[df.ID == 103, 'FirstName'] = "Matt" df.loc[df.ID == 103, 'LastName'] = "Jones"
как уже упоминалось в комментариях, вы также можете сделать назначение для обоих столбцов в одном кадре:
df.loc[df.ID == 103, ['FirstName', 'LastName']] = 'Matt', 'Jones'
обратите внимание, что вам понадобится
pandas
версия 0.11 или новее используйтеloc
для операций назначения перезаписи.
другой способ сделать это-использовать то, что называется цепным назначением. Поведение этого менее стабильно и поэтому не считается лучшим решением (это явно обескуражен в документах), но полезно знать о:
import pandas df = pandas.read_csv("test.csv") df['FirstName'][df.ID == 103] = "Matt" df['LastName'][df.ID == 103] = "Jones"
можно использовать
map
, он может отображать валы из диктофона или даже пользовательской функции.предположим, что это ваш df:
ID First_Name Last_Name 0 103 a b 1 104 c d
создать предсказывает:
fnames = {103: "Matt", 104: "Mr"} lnames = {103: "Jones", 104: "X"}
и карты
df['First_Name'] = df['ID'].map(fnames) df['Last_Name'] = df['ID'].map(lnames)
результат будет такой:
ID First_Name Last_Name 0 103 Matt Jones 1 104 Mr X
или использовать пользовательскую функцию:
names = {103: ("Matt", "Jones"), 104: ("Mr", "X")} df['First_Name'] = df['ID'].map(lambda x: names[x][0])
этот вопрос все еще может быть посещен достаточно часто, что стоит предложить добавление к ответу г-на Кассиса. Элемент
dict
встроенный класс может быть подклассом, так что по умолчанию возвращается для "отсутствующих" ключей. Этот механизм хорошо работает для панд. но видите ниже.таким образом можно избежать ключевых ошибок.
>>> import pandas as pd >>> data = { 'ID': [ 101, 201, 301, 401 ] } >>> df = pd.DataFrame(data) >>> class SurnameMap(dict): ... def __missing__(self, key): ... return '' ... >>> surnamemap = SurnameMap() >>> surnamemap[101] = 'Mohanty' >>> surnamemap[301] = 'Drake' >>> df['Surname'] = df['ID'].apply(lambda x: surnamemap[x]) >>> df ID Surname 0 101 Mohanty 1 201 2 301 Drake 3 401
то же самое можно сделать более просто следующим образом. Использование аргумента по умолчанию для
get
метод объект dict делает ненужным подкласс dict.>>> import pandas as pd >>> data = { 'ID': [ 101, 201, 301, 401 ] } >>> df = pd.DataFrame(data) >>> surnamemap = {} >>> surnamemap[101] = 'Mohanty' >>> surnamemap[301] = 'Drake' >>> df['Surname'] = df['ID'].apply(lambda x: surnamemap.get(x, '')) >>> df ID Surname 0 101 Mohanty 1 201 2 301 Drake 3 401
исходный вопрос относится к конкретному узкому варианту использования. Для тех, кому нужны более общие ответы вот несколько примеров:
создание нового столбца с использованием данных из других столбцов
учитывая фрейм данных ниже:
import pandas as pd import numpy as np df = pd.DataFrame([['dog', 'hound', 5], ['cat', 'ragdoll', 1]], columns=['animal', 'type', 'age']) In[1]: Out[1]: animal type age ---------------------- 0 dog hound 5 1 cat ragdoll 1
ниже мы добавляем новые
description
столбец как объединение других столбцов с помощью+
операция, которая переопределяется для серии. Необычное форматирование строк, f-строки и т. д. не будут работать здесь с+
применяется к скалярам, а не к "примитивным" значениям:df['description'] = 'A ' + df.age.astype(str) + ' years old ' \ + df.type + ' ' + df.animal In [2]: df Out[2]: animal type age description ------------------------------------------------- 0 dog hound 5 A 5 years old hound dog 1 cat ragdoll 1 A 1 years old ragdoll cat
мы
1 years
для кота (вместо1 year
) который мы будем фиксировать ниже с помощью условных обозначений.изменение существующего столбца с условными обозначениями
здесь мы заменяем оригинал
animal
столбец со значениями других столбцов, и с помощьюnp.where
для установки условной подстроки на основе значенияage
:# append 's' to 'age' if it's greater than 1 df.animal = df.animal + ", " + df.type + ", " + \ df.age.astype(str) + " year" + np.where(df.age > 1, 's', '') In [3]: df Out[3]: animal type age ------------------------------------- 0 dog, hound, 5 years hound 5 1 cat, ragdoll, 1 year ragdoll 1
изменение нескольких столбцы с условными обозначениями
более гибкий подход заключается в вызове
.apply()
на весь фрейм данных, а не на один столбец:def transform_row(r): r.animal = 'wild ' + r.type r.type = r.animal + ' creature' r.age = "{} year{}".format(r.age, r.age > 1 and 's' or '') return r df.apply(transform_row, axis=1) In[4]: Out[4]: animal type age ---------------------------------------- 0 wild hound dog creature 5 years 1 wild ragdoll cat creature 1 year
в коде выше