我正在和熊猫一起工作。我的目标是将数据帧中的多个列从包含NaN或字符串数据转换为或多或少的虚拟变量(0表示NaN; 1表示任何字符串)。我想这样做而不使用完整的字符串列表并逐个替换它们,因为存在拼写错误,这会导致错误。我已经能够使用fillna函数将所有NaN数据替换为0,这就像梦一样!
我希望有类似的东西用1代替所有字符串数据,但保留0。我搜索了stackoverflow和其他地方,但收效甚微。
数据看起来大致如此,我只希望将其应用于以T _:
开头的列 fol T_opp T_Dir T_Enh Activity
1 0 0 vo hf
2 vr 0 0 hx
2 0 0 0 fe
3 0 bt 0 rn
我希望输出看起来一样,但是用“vr”“bt”和“vo”每个都用整数1替换。据我所知,pd get_dummies函数不是我正在寻找的对于。我也无法使用replace()来完成这项工作。我尝试使用T / F掩码和零列表,但结果是如此错误我不打算在这里发布代码。
编辑:我在上面的玩具数据中添加了一个额外的列。 “活动”列是一些我不想触及的数据,也是字符串。
答案 0 :(得分:3)
您可以使用正则表达式DataFrame.replace()
执行此操作:
In [14]: df
Out[14]:
fol T_opp T_Dir T_Enh
0 1 0 0 vo
1 2 vr 0 0
2 2 0 0 0
3 3 0 bt 0
In [15]: df.replace(regex={'vr|bt|vo': '1'}).convert_objects(convert_numeric=True)
Out[15]:
fol T_opp T_Dir T_Enh
0 1 0 0 1
1 2 1 0 0
2 2 0 0 0
3 3 0 1 0
如果由于某种原因你反对dict
,你也可以非常明确地说明这一点:
In [19]: df.replace(regex='vr|bt|vo', value='1')
Out[19]:
fol T_opp T_Dir T_Enh
0 1 0 0 1
1 2 1 0 0
2 2 0 0 0
3 3 0 1 0
但等等还有更多!您可以通过传递嵌套的dict
来指定要操作的列(键不能是正则表达式,好吧,它们可以但除了返回帧之外它不会执行任何操作):
In [22]: df.replace({'T_opp': {'vr': 1}, 'T_Dir': {'bt': 1}})
Out[22]:
fol T_opp T_Dir T_Enh
0 1 0 0 vo
1 2 1 0 0
2 2 0 0 0
3 3 0 1 0
编辑:由于您要使用数字1
替换所有字符串(根据您的评论),请执行以下操作:
In [23]: df.replace(regex={r'\D+': 1})
Out[23]:
fol T_opp T_Dir T_Enh
0 1 0 0 1
1 2 1 0 0
2 2 0 0 0
3 3 0 1 0
编辑:Microbenchmarks在这里可能很有用:
安迪的方法(更快):
In [11]: timeit df.convert_objects(convert_numeric=True).fillna(1)
1000 loops, best of 3: 590 µs per loop
DataFrame.replace()
:
In [46]: timeit df.replace(regex={r'\D': 1})
1000 loops, best of 3: 801 µs per loop
如果您有包含要保留的字符串的列
In [45]: cols_to_replace = 'T_opp', 'T_Dir', 'T_Enh'
In [46]: d = dict(zip(cols_to_replace, [{r'\D': 1}] * len(cols_to_replace)))
In [47]: d
Out[47]: {'T_Dir': {'\\D': 1}, 'T_Enh': {'\\D': 1}, 'T_opp': {'\\D': 1}}
In [48]: df.replace(d)
Out[48]:
fol T_opp T_Dir T_Enh Activity
0 1 0 0 1 hf
1 2 1 0 0 hx
2 2 0 0 0 fe
3 3 0 1 0 rn
另一种方法是使用filter
并在替换后将结果连接在一起:
In [10]: df
Out[10]:
fol T_opp T_Dir T_Enh Activity
0 1 0 0 vo hf
1 2 vr 0 0 hx
2 2 0 0 0 fe
3 3 0 bt 0 rn
In [11]: filtered = df.filter(regex='T_.+')
In [12]: res = filtered.replace({'\D': 1})
In [13]: res
Out[13]:
T_opp T_Dir T_Enh
0 0 0 1
1 1 0 0
2 0 0 0
3 0 1 0
In [14]: not_filtered = df[df.columns - filtered.columns]
In [15]: not_filtered
Out[15]:
Activity fol
0 hf 1
1 hx 2
2 fe 2
3 rn 3
In [16]: res.join(not_filtered)
Out[16]:
T_opp T_Dir T_Enh Activity fol
0 0 0 1 hf 1
1 1 0 0 hx 2
2 0 0 0 fe 2
3 0 1 0 rn 3
请注意,不保留列的原始顺序。
您可以使用正则表达式来搜索列名称,如果您要保留许多列,这可能比显式构建列表更有用。 -
运算符与两个Index
对象一起使用时会执行设置差异(df.columns
为Index
)。
除非您的列是混合字符串/整数列,否则您之后可能需要调用DataFrame.convert_objects()
。我的解决方案假定它们都是字符串,因此我致电convert_objects()
将值强制转换为int
dtype
。
答案 1 :(得分:2)
另一种选择是反过来做,首先转换为数字:
In [11]: df.convert_objects(convert_numeric=True)
Out[11]:
fol T_opp T_Dir T_Enh Activity
0 1 0 0 NaN hf
1 2 NaN 0 0 hx
2 2 0 0 0 fe
3 3 0 NaN 0 rn
然后用1:
填写NaNIn [12]: df.convert_objects(convert_numeric=True).fillna(1)
Out[12]:
fol T_opp T_Dir T_Enh Activity
0 1 0 0 1 hf
1 2 1 0 0 hx
2 2 0 0 0 fe
3 3 0 1 0 rn