Создание новых столбцов путем перебора строк в панде.

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 и т. Д. Есть идеи, как улучшить логику, упомянутую выше?

Sanoj
источник
Есть идеи, как это решить? Я все еще жду решения этой проблемы, поскольку мои данные становятся все больше и больше, и существующее решение навсегда превращается в сгенерированные фиктивные столбцы.
Саной

Ответы:

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

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

Dataframe с 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

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

Надеюсь это поможет!

AN6U5
источник
Это не говорит о том, как вы будете динамически получать фиктивные значения (25041) и имена столбцов (т.е. dx1) в цикле for. Я могу получить только один за раз.
Саной,
Посмотри сейчас. Я добавил все детали.
AN6U5
Ваше решение выглядит хорошо, если мне нужно создать фиктивные значения, основанные только на одном столбце, как вы сделали из «E». Но когда мне нужно создать его из нескольких столбцов, и эти значения ячеек не являются уникальными для конкретного столбца, тогда нужно ли снова зацикливать ваш код для всех этих столбцов? Если это так, то как будет заботиться о повторении ценностей? В противном случае он перезаписывает предыдущий столбец-пустышку, созданный с тем же именем. Я добавил свой результат в вопрос выше, чтобы прояснить, не было ли путаницы. В любом случае, спасибо за то, что вы изучаете это
Саной
4

Похоже, вы хотите создать фиктивную переменную из столбца pandas dataframe. К счастью, панды имеют специальный метод для этого: 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  
michaelg
источник
Это выглядит хорошо, но если вы посмотрите внимательно, вы обнаружите, что для value_0 у него нет 1 во всех строках. Поскольку 0 присутствует во всех строках, поэтому value_0 должно иметь 1 во всех строках. То же самое для value_5856, Value_25081 и т. Д. Кажется, что эта логика выбирает значения из столбца и затем не возвращается назад, а движется вперед
Саной
Привет Саной. Несправедливо использовать мое решение и голосовать за меня. Минимум, что вы можете сделать, это обновить ваш вопрос новым прогрессом, который вы сделали, вместо того, чтобы открывать новый вопрос. Если вы хотите, чтобы люди помогали вам, вы должны хорошо с ними играть.
Майкл
Привет, Майкл: Я не собирался тебя голосовать. Я просто снял знак щелчка, так как это решение не отвечало моим потребностям, как было задано в вопросе. Сначала я думал, что все в порядке, но позже, когда я исследовал, я обнаружил расхождения, как указано в ответе выше. Я не получил никакого ответа на этот вопрос, поэтому я создал новый вопрос, где я упомянул свой первоначальный ответ и включил ваш ответ с необходимыми исправлениями. Извините, я не упомянул ваше имя там. Я обновлю это.
Саной