Eu tenho um quadro de dados e um dicionário. Preciso adicionar uma nova coluna ao quadro de dados e calcular seus valores com base no dicionário.
Aprendizado de máquina, adicionando novo recurso com base em alguma tabela:
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)
Espero a seguinte saída:
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
Mikola
fonte
fonte
MultiIIndex
. Alternativa:df['score'] =df.set_index(['gender', 'age', 'cholesterol', 'smoke']).index.map(score).fillna(0).to_numpy()
.df
viaset_index
, um novoSeries
construtor de via. Embora você tenha o benefício do alinhamento de índice ao atribuí-lodf['score']
. Por fim,fillna(0, downcast='infer')
faz o trabalho, mas ninguém deve preferir esta solução demorada com a criação de muitos objetos pandas desnecessariamente.merge
poderia realizar. Achei que a resposta seria publicada rapidamente, então optei por uma alternativa e, por algum motivo, tinha MultiIndices em minha mente. Concordo que esta provavelmente não deve ser a resposta aceita, por isso espero que isso não aconteça.Usando
assign
com uma compreensão de lista, obtendo uma tupla de valores (cada linha) doscore
dicionário, padronizando para zero se não for encontrado.Horários
Dada a variedade de abordagens, pensei que seria interessante comparar alguns dos horários.
fonte
score.get
usoitertuples
ouzip(*map(df.get, df))
... Para reiterar, essa é minha abordagem preferida.df.assign(score=[score.get(t, 0) for t in zip(*map(df.get, df))])
1.0
é o mesmo que o hash,1
portanto, as pesquisas de tuplas devem resultar na mesma resposta, independentemente. Desculpas @Alexander por tantos comentários sobre isso, mas eu só quero que as pessoas votem mais nisso porque ... elas deveriam (-:.values
é carozip(*map(df.get, ['col2', 'col1', 'col5']))
ou obter tuplas de uma modificação dedf
:zip(*map(df.eq(1).get, df))
Você pode usar o mapa , já que score é um dicionário:
Resultado
Como alternativa, você pode usar uma compreensão de lista:
fonte
Lista de compreensão e mapa:
Resultado:
fonte
reindex
Ou
merge
fonte
Pode ser outra maneira seria usando
.loc[]
:fonte
Solução simples de uma linha, Use
get
e emtuple
linha,A solução acima está assumindo que não há outras colunas além das desejadas em ordem. Caso contrário, use apenas colunas
fonte
score.get
é bom. No entanto, você deve preferir uma compreensão, na minha opinião. Veja os horários do @ Alexander .