фрейм данных pandas, добавляющий новые столбцы на основе меток

#python #numpy #pandas

#python #numpy #pandas

Вопрос:

Предположим, у меня есть фрейм данных, подобный этому:

 name   gender
John    1
Alice   0
Michael 1
  

У меня есть другая точка данных, называемая Port, которая указывала, куда отправились эти люди. Порт имеет разные значения (скажем, 1,2 3). Предположим, что Джон приступил к порту 1, Алиса — ко 2, а Майкл — к 3.

Как я могу получить следующую таблицу, используя pandas:

 name  gender  port1   port2   port3
John    1       1       0       0
Alice   0       0       1       0
Michael 1       0       0       1
  

Редактировать
То, как я делаю это сейчас, выполняется полу вручную для каждой метки.

 port_dict = {'port1': 0, 'port2': 1, 'port3': 2}
for port, num in port_dict.items():    
    train_df[port] = train_df.Embarked[train_df.Embarked==num]
    train_df[port].fillna(0, inplace=True)
  

Но это дает мне все 0 в столбцах порта {1,2,3}.

EDIT2 На самом деле, вышеупомянутое решение работает. Но есть ли лучший способ?

Комментарии:

1. Каков ваш подход, где находится ваш код и в какой части вы застряли?

Ответ №1:

Не уверен, откуда берется Embarked атрибут в вашем train_df . Именно так я бы подошел к проблеме, не знаю, можно ли это описать как лучший способ.

 import pandas as pd

df = pd.DataFrame({'name': ['John', 'Alice', 'Michael'], 
              'gender': [1, 0, 1], 'port_num': [1, 2, 3] })

for i in set(df.port_num.values):    
    df['port{0}'.format(i)] = (df.port_num == i).astype(int)
  

Очевидно, что это не будет работать с портами, названными более осмысленно, чем port1 , вам либо понадобится, чтобы port_num столбец был строкой имени порта, либо для создания словаря, как в вашем РЕДАКТИРОВАНИИ.

Ответ №2:

Я использую следующий набор функций:

 def discrim(row, catField, cat, srcField):
    if srcField in row:
        if row[catField]==cat:
            return row[srcField]
        else:
            pass
    else:
        if row[catField]==cat:
            return srcField
    return 0

def CatToAtt(data, source, catField):
    clist = list(data[catField].unique())
    for a in clist:
        data['_att_'   str(a)] = data.apply(lambda x: discrim(x,catField, a, source), axis=1)
    return clist

def getAtts(data):
    alist = []
    for a in data.columns:
        if "_att_" in a:
            alist.append ( a)
    return alist
  

Используйте CatToAtt для преобразования поля, содержащего категоризированные данные, в группу полей, содержащих двоичный код {1,0}, определяющий, относится ли строка к определенному типу категории. Это полезно для подготовки данных для случайных лесов или других процессов статистики / машинного обучения.

Например, скажем, у меня есть поле с именем «Порт», которое содержит значение из [«Лондон», «Саутгемптон», «Шербур», «Квинстаун»] в фрейме данных под названием titanic. Я мог бы запустить следующее:

 CatToAtt(titanic, 1, "Port")
  

И это добавит следующие столбцы в фрейм данных titanic

 ["_att_London", "_att_Southampton", "_att_Cherbourg", "_att_Queenstown"]
  

Каждый заполняется 1, если есть совпадение со столбцом «Порт» и соответствующим значением категории, и 0, если это не так.

Если позже вы захотите быстро получить список всех столбцов, созданных таким образом, просто вызовите getAtts, чтобы вернуть список (предполагается, что никто не собирается использовать используемое здесь соглашение об именовании «att» — достаточно безопасное, но редактируемое на случай, если вы столкнетесь с некоторыми исключениями)

Альтернативой, которую вы могли бы попробовать, может быть:

 def CatToAttAlternative(data, source, catField):
    clist = list(data[catField].unique())
    for a in clist:
        data[str(catField)   str(a)] = data.apply(lambda x: discrim(x, catField, a, source), axis=1)
    return clist
  

Который эффективно выполняет то же самое, только с соглашением об именовании, которое использует имя исходного столбца в качестве префикса вместо «att«, которое при применении к вашему примеру должно возвращать результаты, которые более точно соответствуют вашему примеру (т. Е. Один из {Port1, Port2, Port3} и т.д.)

Надеюсь, это поможет, дайте мне знать, если я смогу объяснить это дальше.