Substituindo valores de coluna em um DataFrame do pandas


141

Estou tentando substituir os valores em uma coluna de um dataframe. A coluna ('feminino') contém apenas os valores 'feminino' e 'masculino'.

Eu tentei o seguinte:

w['female']['female']='1'
w['female']['male']='0' 

Mas receba exatamente a mesma cópia dos resultados anteriores.

Idealmente, gostaria de obter uma saída que se assemelhe ao seguinte loop em termos de elementos.

if w['female'] =='female':
    w['female'] = '1';
else:
    w['female'] = '0';

Examinei a documentação das dicas ( http://pandas.pydata.org/pandas-docs/stable/gotchas.html ), mas não consigo descobrir por que nada acontece.

Qualquer ajuda será apreciada.

Respostas:


259

Se bem entendi, você quer algo assim:

w['female'] = w['female'].map({'female': 1, 'male': 0})

(Aqui eu converto os valores em números em vez de cadeias contendo números. Você pode convertê-los em "1"e "0", se você realmente quiser, mas não sei por que você desejaria isso.)

O motivo pelo qual seu código não funciona é porque o uso ['female']em uma coluna (a segunda 'female'na sua w['female']['female']) não significa "selecionar linhas onde o valor é 'feminino'". Isso significa selecionar linhas onde o índice é 'feminino', das quais pode não haver nenhuma no seu DataFrame.


6
Obrigado. Exatamente o que eu estava procurando. Se eu mapear 'feminino' para 1 e qualquer outra coisa para '0'. Como isso funcionaria?
preto

17
use isso apenas se todos os valores na coluna forem fornecidos na função map. Os valores da coluna não especificados na função map serão substituídos por nan.
22417 Chandra

1
Também gostaria de recomendar utilizando o .locsintaxe para evitar SettingWithCopyWarning: pandas.pydata.org/pandas-docs/stable/...
NickBraunagel

2
em vez de .map eu usei .replace
JS noob

Como faço para me livrar do '.' dos milhares em duas ou mais colunas, não pode descobrir. muito obrigado
M. Mariscal

115

Você pode editar um subconjunto de um quadro de dados usando loc:

df.loc[<row selection>, <column selection>]

Nesse caso:

w.loc[w.female != 'female', 'female'] = 0
w.loc[w.female == 'female', 'female'] = 1

1
Como eu a adaptaria para não precisar selecionar linhas específicas por meio de uma condição, apenas todas as linhas em uma coluna específica? Portanto, altere todas as células em uma coluna para um valor específico.
Dhruv Ghulati

3
@DhruvGhulati, você usaria o df.loc [:, <seleção de coluna>]


38

Leve variação:

w.female.replace(['male', 'female'], [1, 0], inplace=True)

19

Isso também deve funcionar:

w.female[w.female == 'female'] = 1 
w.female[w.female == 'male']   = 0

11

Você também pode usar applycom .getie

w['female'] = w['female'].apply({'male':0, 'female':1}.get):

w = pd.DataFrame({'female':['female','male','female']})
print(w)

Dataframe w:

   female
0  female
1    male
2  female

Usando applypara substituir valores do dicionário:

w['female'] = w['female'].apply({'male':0, 'female':1}.get)
print(w)

Resultado:

   female
0       1
1       0
2       1 

Nota: apply com o dicionário deve ser usado se todos os valores possíveis das colunas no quadro de dados estiverem definidos no dicionário, ele ficará vazio para os que não estão definidos no dicionário.


8

Isso é muito compacto:

w['female'][w['female'] == 'female']=1
w['female'][w['female'] == 'male']=0

Outro bom:

w['female'] = w['female'].replace(regex='female', value=1)
w['female'] = w['female'].replace(regex='male', value=0)

O primeiro exemplo é indexação encadeada e é avisado, pois não pode garantir se o df resultante é uma cópia ou uma exibição. Veja indexação encadeada
Nordle

7

Como alternativa, há a função interna pd.get_dummies para esses tipos de atribuições:

w['female'] = pd.get_dummies(w['female'],drop_first = True)

Isso fornece um quadro de dados com duas colunas, uma para cada valor que ocorre em w ['female'], das quais você solta a primeira (porque você pode deduzi-la da que resta). A nova coluna é automaticamente nomeada como a sequência que você substituiu.

Isso é especialmente útil se você tiver variáveis ​​categóricas com mais de dois valores possíveis. Essa função cria tantas variáveis ​​fictícias necessárias para distinguir entre todos os casos. Cuidado para não atribuir todo o quadro de dados a uma única coluna; em vez disso, se w ['female'] puder ser 'male', 'female' ou 'neutral', faça algo assim:

w = pd.concat([w, pd.get_dummies(w['female'], drop_first = True)], axis = 1])
w.drop('female', axis = 1, inplace = True)

Então você fica com duas novas colunas, fornecendo a codificação fictícia de 'female' e você se livrou da coluna com as strings.


4

Usando Series.mapcomSeries.fillna

Se sua coluna contiver mais seqüências do que apenas femalee male, Series.mapfalhará nesse caso, pois retornará NaNpara outros valores.

É por isso que temos que acorrentá-lo com fillna:

Exemplo por que .mapfalha :

df = pd.DataFrame({'female':['male', 'female', 'female', 'male', 'other', 'other']})

   female
0    male
1  female
2  female
3    male
4   other
5   other
df['female'].map({'female': '1', 'male': '0'})

0      0
1      1
2      1
3      0
4    NaN
5    NaN
Name: female, dtype: object

Para o método correto , encadeamos mapcom fillna, então preenchemos os NaNvalores da coluna original:

df['female'].map({'female': '1', 'male': '0'}).fillna(df['female'])

0        0
1        1
2        1
3        0
4    other
5    other
Name: female, dtype: object

2

Também existe uma função pandaschamada, factorizeque você pode usar para executar automaticamente esse tipo de trabalho. Converte rótulos em números: ['male', 'female', 'male'] -> [0, 1, 0]. Veja esta resposta para mais informações.


0

Eu acho que em resposta deve ser apontado que tipo de objeto você obtém em todos os métodos sugeridos acima: é Series ou DataFrame.

Quando você obtém a coluna por w.female.ou w[[2]](onde, suponha, 2 é o número da sua coluna), você recupera o DataFrame. Portanto, neste caso, você pode usar métodos do DataFrame como .replace.

Quando você usa .locou ilocvocê voltar série, e série não tem .replacemétodo, então você deve usar métodos como apply, mape assim por diante.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.