У меня есть датафрейм и словарь. Мне нужно добавить новый столбец в фрейм данных и рассчитать его значения на основе словаря.
Машинное обучение, добавление новой функции на основе некоторой таблицы:
score = {(1, 45, 1, 1) : 4, (0, 1, 2, 1) : 5}
df = pd.DataFrame(data = {
'gender' : [1, 1, 0, 1, 1, 0, 0, 0, 1, 0],
'age' : [13, 45, 1, 45, 15, 16, 16, 16, 15, 15],
'cholesterol' : [1, 2, 2, 1, 1, 1, 1, 1, 1, 1],
'smoke' : [0, 0, 1, 1, 7, 8, 3, 4, 4, 2]},
dtype = np.int64)
print(df, '\n')
df['score'] = 0
df.score = score[(df.gender, df.age, df.cholesterol, df.smoke)]
print(df)
Я ожидаю следующий вывод:
gender age cholesterol smoke score
0 1 13 1 0 0
1 1 45 2 0 0
2 0 1 2 1 5
3 1 45 1 1 4
4 1 15 1 7 0
5 0 16 1 8 0
6 0 16 1 3 0
7 0 16 1 4 0
8 1 15 1 4 0
9 0 15 1 2 0
python
pandas
dataframe
dictionary
Микола
источник
источник
MultiIIndex
. Альтернатива:df['score'] =df.set_index(['gender', 'age', 'cholesterol', 'smoke']).index.map(score).fillna(0).to_numpy()
.df
viaset_index
, новыйSeries
конструктор via. Хотя вы получаете преимущество выравнивания индекса, когда назначаете егоdf['score']
. Наконец,fillna(0, downcast='infer')
работа выполнена, но никто не должен предпочитать это длинное решение с ненужным созданием множества объектов панд.merge
может сделать простое . Я подумал, что этот ответ будет опубликован быстро, поэтому я выбрал альтернативу, и по некоторым причинам у меня на уме были MultiIndices. Я согласен, это, вероятно, не должен быть принятый ответ, так что, надеюсь, этого не произойдет.Использование
assign
с пониманием списка, получение набора значений (каждой строки) изscore
словаря, по умолчанию равным нулю, если не найден.Задержки
Учитывая разнообразие подходов, мне было бы интересно сравнить некоторые моменты.
источник
score.get
я бы использовалitertuples
илиzip(*map(df.get, df))
... Повторюсь, это мой предпочтительный подход.df.assign(score=[score.get(t, 0) for t in zip(*map(df.get, df))])
1.0
такой же, как и хэш,1
поэтому поиск кортежей должен приводить к одному и тому же ответу независимо от этого. Извинения @Alexander за столько комментариев по этому поводу, но я просто хочу, чтобы люди высказывались об этом больше, потому что ... они должны (-:.values
это дорогоzip(*map(df.get, ['col2', 'col1', 'col5']))
или получить кортежи модификацииdf
:zip(*map(df.eq(1).get, df))
Вы можете использовать карту , так как счет является словарем:
Вывод
В качестве альтернативы вы можете использовать понимание списка:
источник
Понимание списка и карта:
Вывод:
источник
reindex
Или
merge
источник
Может быть, другой способ будет использовать
.loc[]
:источник
Простое однострочное решение, Использование
get
и построчноtuple
,Вышеупомянутое решение предполагает, что нет никаких столбцов, кроме желаемых в порядке. Если нет, просто используйте столбцы
источник
score.get
это хорошо. Тем не менее, вы должны предпочесть понимание, на мой взгляд. Смотрите @ Александр времени.