我有一个pandas数据框,其中包含#34; Survived" 该列有两个可能的值:1和0 我想用[1,0]和0替换为[0,1]。
这些是我尝试过的方法:
首先将列数据类型从int转换为object:
data["Survived"] = data["Survived"].astype(object)
然后尝试更改值(它们都可以使用整数,但不能使用列表):
data["Survived"][data["Survived"] == 1] = 5 # works
data["Survived"][data["Survived"] == 1] = [1, 0] # ValueError: cannot assign mismatch length to masked array
data["Survived"][::].replace(1, 5) # works
data["Survived"][::].replace(1, [1, 0]) # {TypeError}Invalid "to_replace" type: 'int'
以及导致这些错误的其他一些类似方法。
奇怪的是,我可以将值设置为逐个列出 因此,如果我遍历所有条目,我可以将它们全部更改为列表(这给出了我想要的结果):
for i, val in enumerate(data["Survived"]):
data["Survived"][i] = [1, 0] if val == 1 else [0, 1]
这怎么样,既缓慢又丑陋。大熊猫做这件事的方式是什么?
答案 0 :(得分:5)
您可以将numpy.where
用于广播:
data["Survived"] = np.where((data["Survived"] == 1)[:, None], [1,0],[0,1]).tolist()
答案 1 :(得分:3)
如果您的数据框只包含0和1,则可以使用:
data.loc[:, 'Survived'] = data.Survived.apply(lambda x: [0,1] if x == 0 else [1,0])
检查比较中的类型
修改
IMO基于get_dummies
的答案不是最佳的,因为您需要在您的级别导入numpy,因此使用np.where
的答案都不是最佳的。
以下是使用apply
+ lambda
,np.where
和get_dummies
提出的解决方案所用时间的基准。
x轴是行数的log10(即7表示1e7行= 1000万行)。
总结:
对于较少数量的商品,几乎没有差异。
最佳(略有)效果解决方案为np.where
,但您需要导入numpy
第二个最佳选择apply
非常接近第一个。
编辑2
按要求设置此处。
import pandas as pd
import numpy as np
import time
perfdf = pd.DataFrame(index=[3, 4, 5, 6, 7], columns=['apply', 'where', 'get_dummies'])
for s in perfdf.index:
data = pd.DataFrame({'Survived':np.random.randint(low=0,high=2, size=10**s)})
tstart = time.time()
pd.get_dummies(data.Survived).values[:, ::-1].tolist()
tstop = time.time()
perfdf.loc[s, 'get_dummies'] = tstop - tstart
tstart = time.time()
np.where((data["Survived"] == 1)[:, None], [1,0],[0,1]).tolist()
tstop = time.time()
perfdf.loc[s, 'where'] = tstop - tstart
tstart = time.time()
data.Survived.apply(lambda x: [0,1] if x == 0 else [1,0])
tstop = time.time()
perfdf.loc[s, 'apply'] = tstop - tstart
perfdf
答案 2 :(得分:3)
选项1
使用get_dummies
df
Survived
0 1
1 0
2 1
3 0
4 0
5 1
6 1
7 0
df['Survived'] = pd.get_dummies(df.Survived).values[:, ::-1].tolist()
df
Survived
0 [1, 0]
1 [0, 1]
2 [1, 0]
3 [0, 1]
4 [0, 1]
5 [1, 0]
6 [1, 0]
7 [0, 1]
选项2
或者,使用numpy索引,假设您的列只有0和1。
i = np.array([[0, 1], [1, 0]])
df['Survived'] = i[df['Survived'].values].tolist()
df
Survived
0 [1, 0]
1 [0, 1]
2 [1, 0]
3 [0, 1]
4 [0, 1]
5 [1, 0]
6 [1, 0]
7 [0, 1]
<强>计时强>
df = pd.concat([df] * 100000, ignore_index=True)
%timeit pd.get_dummies(df.Survived).values[:, ::-1].tolist()
1 loop, best of 3: 295 ms per loop
%timeit i[df['Survived'].values].tolist()
1 loop, best of 3: 273 ms per loop
%timeit np.where((df["Survived"] == 1)[:, None], [1,0],[0,1]).tolist()
1 loop, best of 3: 285 ms per loop
%timeit df.Survived.apply(lambda x: [0,1] if x == 0 else [1,0])
1 loop, best of 3: 368 ms per loop
所有这些解决方案都具有同等竞争力。这是一个选择问题,你决定使用哪一个。