การสร้างคอลัมน์ใหม่โดยวนซ้ำแถวใน dataframe แพนด้า


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

มีวิธีแก้ปัญหาแบบ pythonic ใน pandas ...

ใช้เวลาน้อยกว่าวินาทีในแล็ปท็อปของฉัน 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

ดาต้าเฟรมขนาดเล็กง่าย ๆ

วิธีการ Binarization -

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

ป้อนคำอธิบายรูปภาพที่นี่

กำหนดเวลาแบบไบนารี (การเข้ารหัสแบบ one-hot) บนดาต้าเบส 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 ได้อย่างไร ฉันสามารถรับได้ทีละหนึ่ง
Sanoj

ลองดูสิ ฉันเพิ่มรายละเอียดทั้งหมด
AN6U5

วิธีแก้ปัญหาของคุณดูดีถ้าฉันต้องการสร้างค่าหุ่นจำลองในคอลัมน์เดียวเมื่อคุณทำจาก "E" แต่เมื่อฉันต้องสร้างมันจากหลายคอลัมน์และค่าเซลล์เหล่านั้นไม่ซ้ำกันในคอลัมน์ใดคอลัมน์หนึ่งฉันต้องลูปรหัสของคุณอีกครั้งสำหรับคอลัมน์เหล่านั้นทั้งหมดหรือไม่ หากเป็นเช่นนั้นการทำซ้ำของค่าจะได้รับการดูแลอย่างไร มิฉะนั้นจะเขียนทับคอลัมน์ dummy ก่อนหน้านี้ที่สร้างด้วยชื่อเดียวกัน ฉันได้เพิ่มผลลัพธ์ในคำถามข้างต้นเพื่อให้ชัดเจนหากมีความสับสน ขอบคุณสำหรับทุกสิ่งที่คุณมองหา
Sanoj

4

ดูเหมือนว่าคุณต้องการสร้างตัวแปรจำลองจากคอลัมน์ดาต้าดาต้าเฟรม 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 มีอยู่ในทุกแถวดังนั้น value_0 ควรมี 1 ในทุกแถว เช่นเดียวกับ value_5856, Value_25081 ฯลฯ ดูเหมือนว่าตรรกะนี้คือการเลือกค่าจากคอลัมน์แล้วไม่กลับไปข้างหน้าแทน
Sanoj

สวัสดี Sanoj มันไม่ยุติธรรมเลยที่จะใช้วิธีแก้ปัญหาและลงคะแนนให้ฉัน อย่างน้อยที่สุดคุณสามารถทำได้คืออัปเดตคำถามของคุณด้วยความคืบหน้าใหม่ที่คุณทำแทนที่จะเปิดคำถามใหม่ หากคุณต้องการให้คนอื่นช่วยคุณคุณควรเล่นให้ดีกับพวกเขา
michaelg

สวัสดีไมเคิล: ฉันไม่มีความตั้งใจที่จะลงคะแนนให้คุณ ฉันเพิ่งลบสัญลักษณ์คลิกเนื่องจากโซลูชันนี้ไม่ตอบสนองความต้องการของฉันตามที่ถาม ตอนแรกฉันคิดว่าตกลง แต่ต่อมาเมื่อฉันตรวจสอบฉันพบความแตกต่างดังที่กล่าวไว้ในคำตอบข้างต้น ฉันไม่ได้รับคำตอบใด ๆ เกี่ยวกับเรื่องนี้ดังนั้นฉันจึงสร้างคำถามใหม่ที่ฉันพูดถึงคำตอบดั้งเดิมของฉันและรวมถึงคำตอบของคุณพร้อมการแก้ไขที่จำเป็น ขออภัยฉันไม่ได้พูดถึงชื่อของคุณที่นั่น ฉันจะอัปเดตนั้น
Sanoj
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.