Adicionar coluna no dataframe da lista

98

Eu tenho um dataframe com algumas colunas como esta:

A   B   C  
0   
4
5
6
7
7
6
5

O intervalo possível de valores em A é apenas de 0 a 7 .

Além disso, tenho uma lista de 8 elementos como esta:

List=[2,5,6,8,12,16,26,32]  //There are only 8 elements in this list

Se o elemento na coluna A é n , eu preciso inserir o n º elemento da lista em uma nova coluna, digamos, 'D'.

Como posso fazer isso de uma vez sem fazer um loop em todo o dataframe?

O dataframe resultante ficaria assim:

A   B   C   D
0           2
4           12
5           16
6           26
7           32
7           32
6           26
5           16

Observação: o dataframe é enorme e a iteração é a última opção. Mas também posso organizar os elementos em 'List' em qualquer outra estrutura de dados como dict, se necessário.

juba
fonte
1
Acho que você precisa de um exemplo de brinquedo (menor), com o resultado desejado. Parece um pouco vago atm.
Andy Hayden,
11
Nunca, jamais chame uma variável de "Lista". Em qualquer idioma.
lucid_dreamer

Respostas:

51

IIUC, se você transformar seu (infelizmente chamado) Listem um ndarray, você pode simplesmente indexar nele naturalmente.

>>> import numpy as np
>>> m = np.arange(16)*10
>>> m[df.A]
array([  0,  40,  50,  60, 150, 150, 140, 130])
>>> df["D"] = m[df.A]
>>> df
    A   B   C    D
0   0 NaN NaN    0
1   4 NaN NaN   40
2   5 NaN NaN   50
3   6 NaN NaN   60
4  15 NaN NaN  150
5  15 NaN NaN  150
6  14 NaN NaN  140
7  13 NaN NaN  130

Aqui eu construí um novo m, mas se você usar m = np.asarray(List), a mesma coisa deve funcionar: os valores em df.Aescolherão os elementos apropriados de m.


Observe que se você estiver usando uma versão antiga do numpy, talvez precise usar m[df.A.values]em seu lugar - no passado, numpynão funcionava bem com os outros, e alguma refatoração pandascausava algumas dores de cabeça. As coisas melhoraram agora.

DSM
fonte
Olá @DSM. Eu entendi o que você está dizendo, mas estou recebendo este erro: Traceback (most recent call last): File "./b.py", line 24, in <module> d["D"] = m[d.A] IndexError: unsupported iterator index
mane
1
@mane: urf, esse é um numpybug antigo . Funciona d["D"] = m[d.A.values]para você?
DSM
283

Basta atribuir a lista diretamente:

df['new_col'] = mylist

Alternativa
Converta a lista em uma série ou matriz e atribua:

se = pd.Series(mylist)
df['new_col'] = se.values

ou

df['new_col'] = np.array(mylist)
pardal
fonte
3
pykernel_launcher.py:1: SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame. Try using .loc[row_indexer,col_indexer] = value instead See the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy """Entry point for launching an IPython kernel.
Ilya Rusin
@sparrow vai usar o pd.Seriesefeito do dtype? Quero dizer, isso deixará flutuadores como flutuadores e strings como strings? Ou os elementos da lista serão padronizados para strings?
3kstc
2
@IlyaRusin, é um falso positivo que pode ser ignorado neste caso. Para mais informações: stackoverflow.com/questions/20625582/…
sparrow
1
Isso pode ser simplificado para: df ['new_col'] = pd.Series (mylist) .values
smartse
17

Uma solução aprimorada no grande do @sparrow.

Deixe df , ser seu conjunto de dados, e mylist a lista com os valores que você deseja adicionar ao dataframe.

Suponhamos que você queira chamar sua nova coluna simplesmente, new_column

Primeiro faça a lista em uma série:

column_values = pd.Series(mylist)

Em seguida, use a função de inserção para adicionar a coluna. Esta função tem a vantagem de permitir que você escolha em que posição deseja colocar a coluna. No exemplo a seguir, posicionaremos a nova coluna na primeira posição a partir da esquerda (definindo loc = 0)

df.insert(loc=0, column='new_column', value=column_values)
Salvatore Cosentino
fonte
Isso não funcionará se você alterar seus índices de df para algo diferente de 1,2,3 ... nesse caso, você tem que adicionar entre as linhas: column_values.index = df.index
Guy's
8

Primeiro, vamos criar o dataframe que você tinha. Vou ignorar as colunas B e C porque não são relevantes.

df = pd.DataFrame({'A': [0, 4, 5, 6, 7, 7, 6,5]})

E o mapeamento que você deseja:

mapping = dict(enumerate([2,5,6,8,12,16,26,32]))

df['D'] = df['A'].map(mapping)

Feito!

print df

Resultado:

   A   D
0  0   2
1  4  12
2  5  16
3  6  26
4  7  32
5  7  32
6  6  26
7  5  16
Phil Cooper
fonte
1
Acho que o OP já sabe fazer isso. Pela minha leitura, o problema está sendo construído a Dpartir dos elementos de Ae List("Se o elemento na coluna A for n, preciso inserir o enésimo elemento da lista em uma nova coluna, diga 'D'.")
DSM
SO se transformou em algum tipo de F (* & nanny state. Obrigado a @DSM pelo comentário, mas não consegui corrigir a postagem até que fosse revisada por pares. E então foi rejeitada porque era muito rápida. E então eu fui capaz de revisar minha própria edição. e então é tarde demais porque uma resposta pior (IMHO) foi "aceita". ASSIM, realmente tenho algumas metannys que são menos do que úteis !!!!
Phil Cooper
Bem, não posso falar pelas babás, mas você descobrirá que sua abordagem é uma ordem de magnitude mais lenta em matrizes longas. Em outros aspectos, é claro, escolher entre np.array(List)[df.A]e df["A"].map(dict(enumerate(List)))é principalmente uma questão de preferência.
DSM
Olá, Phil, Só vi sua solução e o comentário do DSM e nunca mais voltei, pois a solução do DSM funcionou bem para mim. Mas agora, olhando para sua solução, ela também funciona. Eu executei a solução do DSM em meu conjunto de dados de cerca de 200 mil entradas e ele é executado em alguns segundos com todos os outros cálculos que tenho. Eu sou totalmente novo em python-pandas e pessoalmente não estava procurando por nada elegante ou ótimo; tudo o que funcionou estava bem. Mas, honestamente, obrigado pela solução.
mane
2

Velha pergunta; mas eu sempre tento usar o código mais rápido!

Eu tinha uma lista enorme com 69 milhões de uint64. np.array () foi o mais rápido para mim.

df['hashes'] = hashes
Time spent: 17.034842014312744

df['hashes'] = pd.Series(hashes).values
Time spent: 17.141014337539673

df['key'] = np.array(hashes)
Time spent: 10.724546194076538
Mehdi
fonte