Створення нових стовпців шляхом ітерації над рядками в пані даних


10

У мене є кадр даних панди (X11), як це: Насправді у мене є 99 стовпців до 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

Я хочу створити додаткові стовпці для значень комірок, таких як 25041,40391,5856 тощо. Отже, буде колонка 25041 зі значенням як 1 або 0, якщо 25041 зустрічається в цьому конкретному рядку в будь-яких стовпцях dxs. Я використовую цей код, і він працює, коли кількість рядків менше.

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)

Я отримую такий результат:

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

Коли кількість рядків складає багато тисяч або мільйонів, вона зависає і займає назавжди, і я не отримую жодного результату. Зверніть увагу, що значення комірок не є унікальними для стовпців, а повторюються у кількох стовпцях. Наприклад, 40391 зустрічається як в dx1, так і в dx2 і так далі для 0 і 5856 і т. Д. Будь-яка ідея, як покращити згадану вище логіку?


Будь-яка ідея, як це вирішити? Я все ще чекаю, коли це вирішиться, оскільки мої дані стають все більшими та більшими, а існуюче рішення потребує навіщо створюваних фіктивних стовпців.
Саной

Відповіді:


6

У пандах є набагато більше пітонічного рішення ...

Це займає менше секунди на 10 мільйонів рядків на моєму ноутбуці:

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

Ось викладені деталі:

Простий невеликий кадр даних -

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

простий невеликий кадр даних

Метод бінаризації -

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

введіть тут опис зображення

Рамка даних з 10 мільйонами рядків -

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

введіть тут опис зображення

Тимчасова бінаризація (також однокольорове кодування) на 10 мільйонів рядків даних -

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

введіть тут опис зображення

Сподіваюся, це допомагає!


Це не говорить про те, як ви будете динамічно отримувати фіктивне значення (25041) та назви стовпців (тобто dx1) як у циклі for. Я можу отримати лише один за раз.
Саной

Погляньте зараз. Я додав усі деталі.
AN6U5

Ваше рішення виглядає добре, якщо мені потрібно створити фіктивні значення на основі одного стовпця, як ви це зробили з "E". Але коли мені доведеться створити його з декількох стовпців, і ці значення комірок не є унікальними для конкретного стовпця, то чи потрібно мені знову зациклювати ваш код для всіх цих стовпців? Якщо це так, то як буде піклуватися про повторення значень? В іншому випадку він закінчить записувати попередню колонку-манекен, створену з тим же ім’ям. Я додав вищезазначений результат, щоб зрозуміти, чи є якась плутанина. Все одно дякую за те, що ви розглядаєте це.
Саной

4

Схоже, ви хочете створити фіктивну змінну зі стовпця фрейму даних pandas. До щастя, панди мають спеціальний метод для цього: get_dummies(). Ось фрагмент коду, який ви можете адаптувати під свої потреби:

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]

Ось результат 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  

Це виглядає нормально, але якщо ви уважно побачите, то ви побачите, що для value_0 він не має 1 у всіх рядках. Оскільки 0 присутній у всіх рядках, тому значення_0 повинно мати 1 у кожному рядку. Те саме для value_5856, Value_25081 тощо. Здається, ця логіка набирає значення зі стовпця, а потім не повертається назад, а не рухається вперед.
Саной

Привіт Саной. Не дуже справедливо використовувати моє рішення та проголосувати за мене. Найменше, що ви можете зробити - оновити своє запитання новим прогресом, який ви досягли, а не відкривати нове запитання. Якщо ви хочете, щоб люди вам допомагали, вам слід пограти з ними добре.
michaelg

Здрастуйте michaeld: Я не мав наміру голосувати за вас. Я щойно зняв знак натискання, оскільки це рішення не відповідало моїм потребам, про що йдеться в питанні. Спочатку я вважав себе добре, але пізніше, коли досліджував, я виявив розбіжності, про які говорилося у відповіді вище. Я не отримав жодної відповіді на це, тому створив нове запитання, де я згадав свою оригінальну відповідь і включив вашу відповідь із необхідною корекцією. Вибачте, що я там не згадав ваше ім’я. Я це оновлю.
Саной
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.