当列可以有混合类型时,如何在Pandas中创建虚拟变量?

时间:2016-04-02 13:10:03

标签: python pandas

如何在Pandas(Python 2.7)中创建虚拟变量已被多次询问,但我还不知道强大且快速的解决方案。考虑一下这个数据框:

df=pd.DataFrame({'A':[1,2,-1,np.nan, 'rh']})
df
Out[9]: 
     A
0    1
1    2
2   -1
3  NaN
4   rh
是的,它有混合类型。随时都有大数据集(我有数百万行)

我需要创建虚拟变量,如果条件为真,则为1,否则为零。我假设如果Pandas无法执行逻辑比较(比如比较字符串是否大于某个实数),我会得到零。请看一下:

df['dummy2']=(df.A > 0).astype(int)

df['dummy1']=np.where(df.A>0,1,0)

df
Out[12]: 
     A  dummy2  dummy1
0    1       1       1
1    2       1       1
2   -1       0       0
3  NaN       0       0
4   rh       1       1

显然这是有问题的。这里发生了什么?我怎样才能防止这些错误的旗帜?

非常感谢!

2 个答案:

答案 0 :(得分:4)

你可以采取两种方式

In [37]: pd.to_numeric(df.A, errors='coerce').notnull() & (df.A > 0)
Out[37]:
0     True
1     True
2    False
3    False
4    False
Name: A, dtype: bool

In [38]: df.A.apply(np.isreal) & (df.A > 0)
Out[38]:
0     True
1     True
2    False
3    False
4    False
Name: A, dtype: bool

第三个可能很慢

In [39]: df.A.str.isnumeric().isnull() & (df.A > 0)
Out[39]:
0     True
1     True
2    False
3    False
4    False
Name: A, dtype: bool

答案 1 :(得分:2)

更新:@JohnGalt在评论中指出,更好的方法是将pd.to_numericerrors='coerce'一起使用:

# Your condition here, instead of `> 0`, using the fact that NaN > 0 == false
[18]: df['dummy1'] = (pd.to_numeric(df.A, errors='coerce').notnull() > 0).astype('int')
[19]: df
Out[19]:
     A  dummy1
0    1       1
1    2       1
2   -1       0
3  NaN       0
4   rh       0

最好的方法创建这样的虚拟变量的一般方法是:

def foo(a):
    try:
        tmp = int(a)
        return 1 if tmp > 0 else 0 # Your condition here.
    except:
        return 0

[12]: df.A.map(foo)
Out[12]:
0    1
1    1
2    1
3    0
4    0
Name: A, dtype: int64

您正在使用Python comparisons between str and int are (unfortunately) allowed进行操作。 Python 3上的操作失败:

 [5]: df.A > 0
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-5-890e73655a37> in <module>()
----> 1 df.A > 0

/home/utkarshu/miniconda3/envs/py35/lib/python3.5/site-packages/pandas/core/ops.py in wrapper(self, other, axis)
    724                 other = np.asarray(other)
    725
--> 726             res = na_op(values, other)
    727             if isscalar(res):
    728                 raise TypeError('Could not compare %s type with Series'

/home/utkarshu/miniconda3/envs/py35/lib/python3.5/site-packages/pandas/core/ops.py in na_op(x, y)
    646                     result = lib.vec_compare(x, y, op)
    647             else:
--> 648                 result = lib.scalar_compare(x, y, op)
    649         else:
    650

pandas/lib.pyx in pandas.lib.scalar_compare (pandas/lib.c:14186)()

TypeError: unorderable types: str() > int()