我有一个pandas数据框,其中包含“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]
这怎么样,既缓慢又难看。大熊猫的做法是什么?
选项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
所有这些解决方案同样具有竞争力。这是一个选择问题,您决定使用哪一个。
你可以使用numpy.where
广播:
data["Survived"] = np.where((data["Survived"] == 1)[:, None], [1,0],[0,1]).tolist()
如果您的数据框只包含0和1,则可以使用:
data.loc[:, 'Survived'] = data.Survived.apply(lambda x: [0,1] if x == 0 else [1,0])
检查比较中的类型
编辑
IMO基于get_dummies
的答案不是最佳的,也不是使用np.where
的答案,因为你需要在你的级别导入numpy。
这里是使用apply
+ lambda
,np.where
和get_dummies
提出的解决方案的经过时间的基准。
x轴是行数的log10(即7表示1e7行= 1000万行)。
加起来:
np.where
,但你需要导入numpyapply
非常接近第一个。编辑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