将所选的整数值替换为带有Pandas的值列表

问题描述 投票:2回答:3

我有一个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]

这怎么样,既缓慢又难看。大熊猫的做法是什么?

python pandas
3个回答
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

所有这些解决方案同样具有竞争力。这是一个选择问题,您决定使用哪一个。


5
投票

你可以使用numpy.where广播:

data["Survived"] = np.where((data["Survived"] == 1)[:, None], [1,0],[0,1]).tolist()

3
投票

如果您的数据框只包含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 + lambdanp.whereget_dummies提出的解决方案的经过时间的基准。

x轴是行数的log10(即7表示1e7行= 1000万行)。

Benchmark of the solutions

加起来:

  • 对于较少数量的物品,几乎没有区别。
  • 最好的(稍微)性能解决方案是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
© www.soinside.com 2019 - 2024. All rights reserved.