通过遍历pandas数据框中的行来创建新列


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出现在任何dxs列中的特定行中,则将有一个值为250或1或0的列。我正在使用此代码,当行数较少时,它可以工作。

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

当行数成千上万时,它会挂起并永久占用,而我没有得到任何结果。请注意,单元格值不是列唯一的,而是在多列中重复。例如,在dx1中以及在dx2中都出现40391,以此类推,例如0和5856等。您知道如何改善上述逻辑吗?


任何想法如何解决这个问题?随着我的数据越来越大,现有的解决方案永远需要生成虚拟列,我仍在等待解决。
萨诺伊,2016年

Answers:


6

大熊猫还有更多的pythonic解决方案...

这在我的笔记本电脑上的1000万行上花费的时间不到一秒钟:

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

在此处输入图片说明

具有一千万行的数据框-

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

在此处输入图片说明

在1000万行数据帧上进行定时二值化(也称为“一次热编码”)-

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

在此处输入图片说明

希望这可以帮助!


这并没有说明您将如何在for循环中动态获取虚拟值(25041)和列名(即dx1)。我一次只能拿一个。
萨诺伊,2015年

现在看看。我添加了所有详细信息。
AN6U5

如果我仅需要像在“ E”中所做的那样仅基于一列创建伪值,则您的解决方案看起来不错。但是,当我必须从多个列中创建它并且那些单元格值不是特定列所独有的时,我是否需要为所有这些列再次循环代码?如果是这样,那么如何处理重复值?否则,它将覆盖以前创建的同名伪列。我在上面添加了我有问题的结果,以明确是否有任何混淆。无论如何,谢谢您的关注。
萨诺伊,2015年

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,因此value_0在所有行中应具有1。与value_5856,Value_25081等相同。似乎此逻辑是从一列中选择值,然后不返回,而是向前移动。
萨诺伊2015年

嗨Sanoj 使用我的解决方案并否决我是不公平的。您至少可以做的是使用新的进度更新问题,而不是打开新问题。如果您希望别人帮助您,您应该和他们一起玩。
michaelg 2015年

你好迈克尔德:我无意将你投反对票。由于该解决方案无法满足我的要求,因此我刚刚点击了点击标志。最初我认为还可以,但是后来我进行调查时发现了上面答复中提到的差异。我没有得到任何答复,因此我创建了一个新问题,其中提到了我的原始答案,并在您的答复中包括了需要纠正的内容。对不起,我在那儿没有提到你的名字。我会更新的。
萨诺伊,2015年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.