Creazione di nuove colonne ripetendo le righe nel frame di dati Panda


10

Ho un frame di dati Panda (X11) come questo: In realtà ho 99 colonne fino a 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

Voglio creare colonne aggiuntive per valori di cella come 25041,40391,5856 ecc. Quindi ci sarà una colonna 25041 con valore come 1 o 0 se 25041 si verifica in quella particolare riga in qualsiasi colonna dxs. Sto usando questo codice e funziona quando il numero di righe è inferiore.

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)

Sto ottenendo risultati in questo modo:

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 il numero di righe è di molte migliaia o in milioni, si blocca e impiega un'eternità e non ottengo alcun risultato. Si noti che i valori delle celle non sono univoci per la colonna, ma si ripetono in più colonne. Ad esempio, 40391 si verifica in dx1 e in dx2 e così via per 0 e 5856 ecc. Qualche idea su come migliorare la logica sopra menzionata?


Qualche idea su come risolverlo? Sto ancora aspettando che questo si risolva mentre i miei dati diventano sempre più grandi e la soluzione esistente impiega per sempre colonne fittizie generate.
Sanoj,

Risposte:


6

C'è una soluzione molto più pitonica nei panda ...

Questo richiede meno di un secondo su 10 milioni di righe sul mio laptop:

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

Ecco i dettagli indicati:

Piccolo frame di dati semplice -

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

piccolo frame di dati semplice

Metodo di binarizzazione -

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

inserisci qui la descrizione dell'immagine

Dataframe con 10 milioni di righe -

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

inserisci qui la descrizione dell'immagine

Binarizzazione temporizzata (nota anche come codifica one-hot) su frame di dati da 10 milioni di righe -

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

inserisci qui la descrizione dell'immagine

Spero che sia di aiuto!


Questo non dice come otterrai dinamicamente il valore fittizio (25041) e i nomi delle colonne (cioè dx1) entrambi nel ciclo for. Posso ottenerne solo uno alla volta.
Sanoj,

Dai un'occhiata adesso. Ho aggiunto tutti i dettagli.
AN6U5,

La tua soluzione sembra buona se ho bisogno di creare valori fittizi basati su una colonna solo come hai fatto da "E". Ma quando devo crearlo da più colonne e quei valori di cella non sono univoci per una particolare colonna, allora devo ripetere il ciclo del codice per tutte quelle colonne? In tal caso, come verrà curata la ripetizione dei valori? Altrimenti sovrascriverà la colonna fittizia precedente creata con lo stesso nome. Ho aggiunto il mio risultato nella domanda sopra per chiarire se c'era confusione. Grazie comunque per averci esaminato.
Sanoj,

4

Sembra che tu voglia creare una variabile fittizia da una colonna di frame di dati Panda. Fortunatamente, i panda ha un metodo speciale per esso: get_dummies(). Ecco uno snippet di codice che puoi adattare alle tue esigenze:

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]

Ecco l'output di 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  

Sembra OK ma se lo vedrai attentamente, troverai che per value_0, non ha 1 in tutte le righe. Poiché 0 è presente in tutte le righe, quindi value_0 dovrebbe avere 1 in tutte le righe. Lo stesso vale per value_5856, Value_25081 ecc. Sembra che questa logica stia selezionando valori da una colonna e quindi non torni indietro invece di andare avanti.
Sanoj,

Ciao Sanoj. Non è proprio corretto usare la mia soluzione e votarmi. Il minimo che puoi fare è aggiornare la tua domanda con i nuovi progressi che hai fatto invece di aprire una nuova domanda. Se vuoi che le persone ti aiutino, dovresti giocare bene con loro.
michaelg

Ciao michaeld: non avevo intenzione di votarti. Ho appena tolto il segno del clic poiché questa soluzione non ha soddisfatto le mie esigenze come richiesto. Inizialmente ho pensato bene ma più tardi quando ho investigato ho trovato le discrepanze come menzionato nella risposta sopra. Non ho ricevuto alcuna risposta, quindi ho creato una nuova domanda in cui ho menzionato la mia risposta originale e ho incluso la tua risposta con le correzioni necessarie. Mi dispiace non ho menzionato il tuo nome lì. Lo aggiornerò.
Sanoj,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.