Criando novas colunas iterando sobre linhas no dataframe do pandas

10

Eu tenho um quadro de dados pandas (X11) como este: Na verdade, eu tenho 99 colunas até dx99

    dx1      dx2    dx3    dx4
0   25041   40391   5856    0
1   25041   40391   25081   5856
2   25041   40391   42822   0
3   25061   40391   0       0
4   25041   40391   0       5856
5   40391   25002   5856    3569

Eu quero criar colunas adicionais para valores de célula como 25041,40391,5856 etc. Portanto, haverá uma coluna 25041 com o valor 1 ou 0 se 25041 ocorrer nessa linha específica em qualquer coluna dxs. Estou usando esse código e funciona quando o número de linhas é menor.

mat = X11.as_matrix(columns=None)
values, counts = np.unique(mat.astype(str), return_counts=True)

for x in values:
    X11[x] = X11.isin([x]).any(1).astype(int)

Estou obtendo resultado assim:

dx1     dx2     dx3    dx4  0   25002   25041   25061   25081   3569    40391   42822   5856
25041   40391   5856    0   0   0       1       0       0       0          1        0       1
25041   40391   25081  5856 0   0       1       0       1       0            1      0       1
25041   40391   42822   0   0   0       1       0       0       0           1       1       0
25061   40391   0       0   0   0       0       1       0       0          1        0       0
25041   40391   0    5856   0   0       1       0       0       0          1        0       1
40391   25002 5856   3569   0   1       0       0       0       1          1        0       1

Quando o número de linhas é de muitos milhares ou milhões, ele fica suspenso e leva uma eternidade e não estou obtendo nenhum resultado. Por favor, veja que os valores das células não são exclusivos da coluna, ao invés de repetir em várias colunas. Por exemplo, 40391 está ocorrendo no dx1 e no dx2 e assim por diante para 0 e 5856 etc. Alguma idéia de como melhorar a lógica mencionada acima?

Sanoj
fonte
Alguma idéia de como resolver isso? Ainda estou esperando que isso seja resolvido, pois meus dados estão ficando cada vez maiores e a solução existente leva para sempre as colunas fictícias geradas.
Sanoj 6/01/16

Respostas:

6

Há uma solução muito mais pythonic em pandas ...

Isso leva menos de um segundo em 10 milhões de linhas no meu laptop:

for x in X11.E.unique():
    X11[x]=(X11.E==x).astype(int)
X11

Aqui estão os detalhes apresentados:

Dataframe pequeno e simples -

import numpy as np
import pandas as pd

X11 = pd.DataFrame(np.random.randn(6,4), columns=list('ABCD'))
X11['E'] = [25223, 112233,25223,14333,14333,112233]
X11

dataframe pequeno e simples

Método de binarização -

for x in X11.E.unique():
    X11[x]=(X11.E==x).astype(int)
X11

insira a descrição da imagem aqui

Dataframe com 10 milhões de linhas -

pd.set_option("display.max_rows",20)
X12 = pd.DataFrame(np.random.randn(10000000,4), columns=list('ABCD'))
foo = [25223, 112233,25223,14333,14333,112233]
bar=[]
import random
for x in range(10000000):
    bar.append(random.choice(foo))
X12['E'] = bar
X12

insira a descrição da imagem aqui

Binarização temporizada (também conhecida como codificação one-hot) em 10 milhões de quadros de dados de linha -

import time
start = time.clock()

for x in X12.E.unique():
    X12[x]=(X12.E==x).astype(int)
elapsed = (time.clock() - start)

print "This is the time that this took in seconds: ",elapsed

X12

insira a descrição da imagem aqui

Espero que isto ajude!

AN6U5
fonte
Isso não diz como você obterá dinamicamente o valor fictício (25041) e os nomes das colunas (por exemplo, dx1), ambos no loop for. Eu posso conseguir apenas um de cada vez.
Sanoj
Dê uma olhada agora. Eu adicionei todos os detalhes.
AN6U5
Sua solução parece boa se eu precisar criar valores fictícios com base em uma coluna apenas como você fez em "E". Mas quando tenho que criá-lo a partir de várias colunas e esses valores de célula não são exclusivos para uma coluna específica, preciso repetir o código novamente para todas essas colunas? Se for esse o caso, então como a repetição de valores será resolvida? Caso contrário, ele substituirá a coluna fictícia anterior criada com o mesmo nome. Eu adicionei meu resultado na pergunta acima para deixar claro se houve alguma confusão. Obrigado de qualquer maneira por você olhar para ele.
21315 Sanoj
4

Parece que você deseja criar uma variável fictícia a partir de uma coluna de quadro de dados do pandas. Felizmente, pandas tem um método especial para ele: get_dummies(). Aqui está um trecho de código que você pode adaptar para sua necessidade:

import pandas as pd
data = pd.read_clipboard(sep=',')

#get the names of the first 3 columns
colN = data.columns.values[:3]

#make a copy of the dataframe
data_transformed = data

#the get_dummies method is doing the job for you
for column_name in colN:
    dummies = pd.get_dummies(data_transformed[column_name], prefix='value', prefix_sep='_')
    col_names_dummies = dummies.columns.values

    #then you can append new columns to the dataframe
    for i,value in enumerate(col_names_dummies):
        data_transformed[value] = dummies.iloc[:,i]

Aqui está a saída de data_transformed:

         dx1    dx2    dx3   dx4    dx5    dx6    dx7  value_25041  value_25061  0  25041  40391   5856     0  V4511  V5867  30000            1            0   
    1  25041  40391  25081  5856   5363   3572      0            1            0   
    2  25041  40391  42822     0   5856      0      0            1            0   
    3  25061  40391      0     0      0      0      0            0            1   
    4  25041  40391      0  5856  25081  V4511  25051            1            0   

      value_40391  value_0  value_5856  value_25081  value_42822  
    0            1        0           1            0            0  
    1            1        0           0            1            0  
    2            1        0           0            0            1  
    3            1        1           0            0            0  
    4            1        1           0            0            0  
michaelg
fonte
Parece bom, mas se você vir com cuidado, verá que, para o valor_0, ele não possui 1 em todas as linhas. Como 0 está presente em todas as linhas, o valor_0 deve ter 1 em todas as linhas. O mesmo vale para value_5856, Value_25081 etc. Parece que essa lógica está escolhendo valores de uma coluna e depois não voltando atrás.
Sanoj
Oi Sanoj. Não é realmente justo usar minha solução e votar em mim. O mínimo que você pode fazer é atualizar sua pergunta com o novo progresso feito em vez de abrir uma nova pergunta. Se você quer que as pessoas o ajudem, você deve ser legal com elas.
22615 michaelg
Olá Michaeld: Eu não tinha intenção de votar em você. Acabei de retirar o sinal de clique, pois essa solução não atendia às minhas necessidades, conforme solicitado na pergunta. Inicialmente, pensei que estava bem, mas mais tarde, quando investiguei, encontrei as discrepâncias mencionadas na resposta acima. Como não recebi nenhuma resposta, criei uma nova pergunta em que mencionei minha resposta original e incluí sua resposta com a correção necessária. Desculpe, eu não mencionei seu nome lá. Vou atualizar isso.
Sanoj