Как я могу перебрать все строки кадра данных, чтобы применить функцию поиска к строковому значению и применить результат к новому столбцу? - PullRequest
2 голосов
/ 11 июля 2019

У меня есть датафрейм с несколькими столбцами персональных данных для каждой строки (человек).Я хочу применить функцию для поиска города или штата каждого человека в региональных списках, а затем применить результат к новому столбцу «Регион» в том же кадре данных.

Мне удалось заставить ту же операцию работать с очень упрощенным кадром данных с категориями для цветов и транспортных средств (см. Ниже).Но когда я пытаюсь сделать это с личными данными, это не будет работать так же, и я не понимаю, почему.

Я прочитал много статей о лямбда-функциях, но я думаю, что то, что я спрашиваю, слишком сложно для этого.Большинство решений имеют дело с числовыми данными, и я использую строки, но, как я уже сказал, я смог заставить их работать с одним набором данных.Очевидно, я новичок здесь.Я также был бы признателен за совет о том, как создать новый столбец как часть функции, вместо того, чтобы создавать его как отдельный шаг, но это меня не расстраивает так сильно, как основной вопрос.

Этопример работает:

# Python: import pandas
import pandas as pd
# Simple dataframe. Empty column 'type'.
df = pd.DataFrame({'one':['1','2','3','4','5','6','7','8'], 
                  'two':['A','B','C','D','E','F','G','H'], 
                  'three': ['car','bus','red','blue','truck','pencil','yellow','green'],
                  'type':''})

df отображает:

    one two three   type
0   1   A   car     
1   2   B   bus     
2   3   C   red     
3   4   D   blue    
4   5   E   truck   
5   6   F   pencil  
6   7   G   yellow  
7   8   H   green   

Теперь определите списки и пользовательскую функцию:

# Definte lists of colors and vehicles
colors = ['red','blue','green','yellow']
vehicles = ['car','truck','bus','motorcycle']

# Create function 'celltype' to return values based on x
def celltype (x):
    if x in colors: return 'color' 
    elif x in vehicles: return 'vehicle'
    else: return 'other'

Затем создайте цикл для итерации по каждой строке ипримените функцию:

# Write loop to iterate through df rows and apply function 'celltype' to column 'three' in each row
for index, row in df.iterrows(): 
    row['type'] = celltype(row['three'])

И в этом случае результат будет именно тем, что я хочу:

    one two three   type
0   1   A   car     vehicle
1   2   B   bus     vehicle
2   3   C   red     color
3   4   D   blue    color
4   5   E   truck   vehicle
5   6   F   pencil  other
6   7   G   yellow  color
7   8   H   green   color


Этот пример не работает,и я не знаю почему:

df1 = pd.DataFrame({'Last Name':['SMITH','JONES','WILSON','DOYLE','ANDERSON'], 'First Name':['TOM','DICK','HARRY','MICHAEL','KEVIN'],
                    'Code':[12,34,56,78,90], 'Deparment':['Research','Management','Maintenance','Marketing','IT'],
                    'City':['NEW YORK','BOSTON','SAN FRANCISCO','DALLAS','DETROIT'], 'State':['NY','MA','CA','TX','MI'], 'Region':''}) 

df1 отображает:

    Last Name   First Name  Code    Deparment   City        State   Region
0   SMITH       TOM         12  Research        NEW YORK    NY  
1   JONES       DICK        34  Management      BOSTON      MA  
2   WILSON      HARRY       56  Maintenance     SAN FRANCISCO   CA  
3   DOYLE       MICHAEL     78  Marketing       DALLAS      TX  
4   ANDERSON    KEVIN       90  IT              DETROIT     MI  

Опять определяя списки и функции:

# Define lists for regions
east = ['NEW YORK','BOSTON']
west = ['SAN FRANCISCO','LOS ANGELES']
south = ['TX']

# Create function 'region' to return values based on x
def region (x):
    if x in east: return 'east' 
    elif x in west: return 'west'
    elif x in south: return 'south'
    else: return 'other'

# Write loop to iterate through df1 rows and apply function 'region' to column 'City' in each row
for index, row in df1.iterrows(): 
    row['Region'] = region(row['City'])
    if row['Region'] == 'other': row['Region'] = region(row['State'])

Это приводит к неизменностиdf1.Столбец «Регион» остается пустым.Мы должны видеть «восток», «восток», «запад», «юг», «другое».Единственным отличием в коде является дополнительный оператор if, чтобы перехватить Даллас по штатам (что мне нужно для моего набора данных реального мира).Но я думаю, что эта строка звучит правильно, и я получаю тот же результат без нее.

Ответы [ 2 ]

1 голос
/ 12 июля 2019

Во-первых, apply и iterrows медленные, поэтому старайтесь никогда не использовать их.

В этой ситуации я обычно делаю пару из forward и backward dicts:

forward = {'east': east,
           'west': west,
           'south': south}

backward = {x:k for k,v in forward.items() for x in v}

А затем обновите map.Поскольку вы хотите обновить на основе двух столбцов, fillna будет полезно:

df1['Region'] = (df1['State'].map(backward)
                    .fillna(df1['City'].map(backward))
                    .fillna('other')
                )

дает:

  Last Name First Name  Code    Deparment           City State Region
0     SMITH        TOM    12     Research       NEW YORK    NY   east
1     JONES       DICK    34   Management         BOSTON    MA   east
2    WILSON      HARRY    56  Maintenance  SAN FRANCISCO    CA   west
3     DOYLE    MICHAEL    78    Marketing         DALLAS    TX  south
4  ANDERSON      KEVIN    90           IT        DETROIT    MI  other
0 голосов
/ 12 июля 2019

Ваша проблема связана с использованием iterrows.В общем, вы никогда не должны изменять то, что вы повторяете.В этом случае iterrows создает копию ваших данных и фактически не изменяет вашу df1.Копия - это то, что может произойти или не произойти в зависимости от обстоятельств, поэтому вам следует избегать чего-то подобного.

Вы можете убедиться, что он изменяет оригинал, вызвав Dataframe напрямую с помощью at:

for index, row in df1.iterrows(): 
    df1.at[index, 'Region'] = region(row['City'])
    if df1.at[index, 'Region'] == 'other': df1.at[index, 'Region'] = region(row['State'])
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...