Tworzenie nowych kolumn przez powtarzanie wierszy w ramce danych pandy

10

Mam ramkę danych pand (X11) taką jak ta: w rzeczywistości mam 99 kolumn do 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

Chcę utworzyć dodatkowe kolumny dla wartości komórek, takich jak 25041, 40391,5856 itd. Więc będzie kolumna 25041 o wartości 1 lub 0, jeśli 25041 wystąpi w tym konkretnym wierszu w dowolnych kolumnach dxs. Używam tego kodu i działa, gdy liczba wierszy jest mniejsza.

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)

Otrzymuję taki wynik:

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

Kiedy liczba rzędów wynosi wiele tysięcy lub milionów, zawiesza się i trwa wiecznie, a ja nie osiągam żadnych rezultatów. Proszę zauważyć, że wartości komórek nie są unikatowe dla kolumn, lecz powtarzają się w wielu kolumnach. Na przykład 40391 występuje w dx1, a także w dx2 itd. Dla 0 i 5856 itd. Jakiś pomysł, jak poprawić logikę wspomnianą powyżej?

Sanoj
źródło
Masz pomysł, jak to rozwiązać? Nadal czekam na rozwiązanie tego problemu, ponieważ moje dane stają się coraz większe, a istniejące rozwiązanie na zawsze generuje fikcyjne kolumny.
Sanoj

Odpowiedzi:

6

W pandach jest o wiele więcej pythonowego rozwiązania ...

Zajmuje to mniej niż sekundę w 10 milionach wierszy na moim laptopie:

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

Oto przedstawione szczegóły:

Prosta mała ramka danych -

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

prosta mała ramka danych

Metoda binaryzacji -

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

wprowadź opis zdjęcia tutaj

Ramka danych z 10 milionami wierszy -

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

wprowadź opis zdjęcia tutaj

Czasowa binaryzacja (inaczej kodowanie „na gorąco”) na 10 milionach ramek danych -

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

wprowadź opis zdjęcia tutaj

Mam nadzieję że to pomoże!

AN6U5
źródło
Nie mówi to, w jaki sposób dynamicznie otrzymasz wartość fikcyjną (25041) i nazwy kolumn (tj. Dx1) zarówno w pętli for. Mogę dostać tylko jeden na raz.
Sanoj
Spójrz teraz. Dodałem wszystkie szczegóły.
AN6U5,
Twoje rozwiązanie wygląda dobrze, jeśli muszę utworzyć wartości zastępcze na podstawie tylko jednej kolumny, tak jak zrobiłeś to z „E”. Ale kiedy muszę go utworzyć z wielu kolumn, a te wartości komórek nie są unikalne dla konkretnej kolumny, to czy muszę ponownie zapętlić kod dla wszystkich tych kolumn? Jeśli tak jest, to w jaki sposób zostanie przeprowadzone powtórzenie wartości? W przeciwnym razie nadpisuje poprzednią fikcyjną kolumnę utworzoną o tej samej nazwie. Dodałem swój wynik w powyższym pytaniu, aby wyjaśnić, czy było jakieś zamieszanie. W każdym razie dziękuję, że zaglądasz w to.
Sanoj
4

Wygląda na to, że chcesz utworzyć zmienną fikcyjną z kolumny ramki danych pandy. Na szczęście pandy mają specjalną metodę:get_dummies() . Oto fragment kodu, który możesz dostosować do swoich potrzeb:

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]

Oto wynik 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  
Michael
źródło
Wygląda OK, ale jeśli zobaczysz uważnie, przekonasz się, że dla value_0 nie ma 1 we wszystkich wierszach. Ponieważ 0 jest obecne we wszystkich wierszach, dlatego wartość_0 powinna mieć 1 we wszystkich wierszach. To samo dla value_5856, Value_25081 itd. Wygląda na to, że ta logika wybiera wartości z kolumny, a następnie nie wraca zamiast tego do przodu.
Sanoj
Cześć Sanoj. Używanie mojego rozwiązania i głosowanie za mną jest niesprawiedliwe. Możesz przynajmniej zaktualizować swoje pytanie o nowy postęp, który zrobiłeś, zamiast otwierać nowe pytanie. Jeśli chcesz, aby ludzie ci pomagali, powinieneś z nimi dobrze się bawić.
michaelg,
Cześć Michaeld: Nie miałem zamiaru głosować za tobą. Właśnie zdjąłem znak kliknięcia, ponieważ to rozwiązanie nie spełniło moich potrzeb. Początkowo myślałem, że OK, ale później, kiedy badałem, zauważyłem rozbieżności, jak wspomniano w odpowiedzi powyżej. Nie otrzymałem żadnej odpowiedzi na to pytanie, dlatego stworzyłem nowe pytanie, w którym wspomniałem o mojej pierwotnej odpowiedzi i umieściłem twoją odpowiedź z konieczną poprawką. Przepraszam, że nie wspomniałem tam twojego imienia. Zaktualizuję to.
Sanoj