Como fazer isso em pandas:
Eu tenho uma função extract_text_features
em uma única coluna de texto, retornando várias colunas de saída. Especificamente, a função retorna 6 valores.
A função funciona, no entanto, parece não haver nenhum tipo de retorno adequado (pandas DataFrame / numpy array / lista Python), de modo que a saída possa ser atribuída corretamente df.ix[: ,10:16] = df.textcol.map(extract_text_features)
Então, acho que preciso voltar a iterar com isso df.iterrows()
, de acordo com isso ?
ATUALIZAÇÃO: A iteração df.iterrows()
é pelo menos 20x mais lenta, então eu me rendi e dividi a função em seis .map(lambda ...)
chamadas distintas .
ATUALIZAÇÃO 2: esta pergunta foi feita em torno da v0.11.0 . Portanto, grande parte das perguntas e respostas não são muito relevantes.
df.ix[: ,10:16]
. Eu acho que você terá quemerge
seus recursos no conjunto de dados.apply
Respostas:
Com base na resposta do usuário1827356, você pode fazer a atribuição de uma só vez usando
df.merge
:EDIT: Esteja ciente do enorme consumo de memória e baixa velocidade: https://ys-l.github.io/posts/2015/08/28/how-not-to-use-pandas-apply/ !
fonte
Eu costumo fazer isso usando
zip
:fonte
temp = list(zip(*df['num'].map(powers))); for i, c in enumerate(columns): df[c] = temp[c]
for i, c in enumerate(columns): df[c] = temp[i]
. Graças a isso, eu realmente tenho o objetivo deenumerate
: Dzip(*df['col'].map(function))
provavelmente é o caminho a percorrer.Isto é o que eu fiz no passado
Edição para integridade
fonte
df[['col1', 'col2']] = df['col3'].apply(lambda x: pd.Series('val1', 'val2'))
Esta é a maneira correta e mais fácil de fazer isso para 95% dos casos de uso:
fonte
pd.Series({k:v})
e serializar a atribuição da coluna como na resposta de Ewan?Em 2018, eu uso
apply()
com argumentoresult_type='expand'
fonte
pd.Series
que é sempre bom em relação a problemas de desempenhodf.apply
retornar adict
, as colunas serão nomeadas de acordo com as teclas.Apenas use
result_type="expand"
fonte
Resumo: se você deseja criar apenas algumas colunas, use
df[['new_col1','new_col2']] = df[['data1','data2']].apply( function_of_your_choosing(x), axis=1)
Para esta solução, o número de novas colunas que você está criando deve ser igual ao número de colunas que você usa como entrada para a função .apply (). Se você quiser fazer outra coisa, dê uma olhada nas outras respostas.
Detalhes Digamos que você tenha um quadro de dados de duas colunas. A primeira coluna é a altura de uma pessoa quando ela tem 10 anos; o segundo é a altura da pessoa quando ela tem 20 anos.
Suponha que você precise calcular a média das alturas de cada pessoa e a soma das alturas de cada pessoa. São dois valores por cada linha.
Você pode fazer isso através da seguinte função, que será aplicada em breve:
Você pode usar esta função da seguinte maneira:
(Para ficar claro: essa função de aplicação recebe os valores de cada linha no dataframe subconjunto e retorna uma lista.)
No entanto, se você fizer isso:
você criará uma nova coluna que contém as listas [média, soma], que você provavelmente gostaria de evitar, porque isso exigiria outro Lambda / Apply.
Em vez disso, você deseja dividir cada valor em sua própria coluna. Para fazer isso, você pode criar duas colunas ao mesmo tempo:
fonte
df["mean"], df["sum"] = df[['height_at_age_10','height_at_age_20']] .apply(mean_and_sum(x),axis=1)
return pd.Series([mean,sum])
Para mim, isso funcionou:
Entrada df
Função
Crie 2 novas colunas:
Resultado:
fonte
Procurei várias maneiras de fazer isso e o método mostrado aqui (retornando uma série de pandas) não parece ser mais eficiente.
Se começarmos com um quadro de dados grande, de dados aleatórios:
O exemplo mostrado aqui:
Um método alternativo:
Pela minha conta, é muito mais eficiente pegar uma série de tuplas e depois convertê-las em um DataFrame. Eu ficaria interessado em ouvir o pensamento das pessoas, se houver um erro no meu trabalho.
fonte
A solução aceita será extremamente lenta para muitos dados. A solução com o maior número de votos positivos é um pouco difícil de ler e também lenta com os dados numéricos. Se cada nova coluna puder ser calculada independentemente das outras, eu atribuiria cada uma delas diretamente sem usar
apply
.Exemplo com dados de caracteres falsos
Crie 100.000 seqüências de caracteres em um DataFrame
Digamos que desejássemos extrair alguns recursos de texto, como feito na pergunta original. Por exemplo, vamos extrair o primeiro caractere, contar a ocorrência da letra 'e' e colocar em maiúscula a frase.
Horários
Surpreendentemente, você pode obter um melhor desempenho percorrendo cada valor
Outro exemplo com dados numéricos falsos
Crie 1 milhão de números aleatórios e teste a
powers
função de cima.A atribuição de cada coluna é 25x mais rápida e muito legível:
Fiz uma resposta semelhante com mais detalhes aqui sobre por que
apply
normalmente não é o caminho a percorrer.fonte
Postaram a mesma resposta em duas outras perguntas semelhantes. A maneira como prefiro fazer isso é agrupar os valores de retorno da função em uma série:
E, em seguida, use apply da seguinte maneira para criar colunas separadas:
fonte
você pode retornar a linha inteira em vez de valores:
onde a função retorna a linha
fonte
extract_text_features
a cada coluna do df, apenas para a coluna de textodf.textcol
Isso funcionou para mim. Nova coluna será criada com os dados da coluna antiga processados.
fonte