更改数据框中的多个位置的最快方法

时间:2018-08-01 14:54:05

标签: python python-3.x pandas

我有一个具有100万行的pandas数据框。我想用另一组值替换一列中900,000行中的值。有没有没有for循环的快速方法(需要我花两天时间完成)?

例如,查看此示例数据框,其中我将100万行压缩为8行

import numpy as np
import pandas as pd

df = pd.DataFrame()
df['a'] = [-1,-3,-4,-4,-3, 4,5,6]
df['b'] = [23,45,67,89,0,-1, 2, 3]

L2 = [-1,-3,-4]
L5 = [9,10,11]

我想在可能的情况下在一次镜头中替换a分别为-1,-3,-4的值,或者在没有for循环的情况下尽快替换。

关键部分是必须根据需要重复L5中的值。

我尝试过

df.loc[df.a < 0, 'a'] = L5

但这仅在len(df.a.values) == len(L5)

时有效

2 个答案:

答案 0 :(得分:6)

list中由两个zip创建的字典使用map,最后在fillna中替换为原始的不匹配值:

d = dict(zip(L2, L5))
print (d)
{-1: 9, -3: 10, -4: 11}

df['a'] = df['a'].map(d).fillna(df['a'])
print (df)
      a   b
0   9.0  23
1  10.0  45
2  11.0  67
3  11.0  89
4  10.0   0
5   4.0  -1
6   5.0   2
7   6.0   3

性能

取决于list s的替换长度值的数量:

list的长度为100

np.random.seed(123)
N = 1000000

df = pd.DataFrame({'a':np.random.randint(1000, size=N)})

L2 = np.arange(100)
L5 = np.arange(100) + 10


In [336]: %timeit df['d'] = np.select([df['a'] == i for i in L2], L5, df['a'])
180 ms ± 1.07 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

In [337]: %timeit df['a'].map(dict(zip(L2, L5))).fillna(df['a'])
56.9 ms ± 2.55 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

如果列表的长度很小(例如3

np.random.seed(123)
N = 1000000

df = pd.DataFrame({'a':np.random.randint(100, size=N)})

L2 = np.arange(3)
L5 = np.arange(3) + 10

In [339]: %timeit df['d'] = np.select([df['a'] == i for i in L2], L5, df['a'])
11.9 ms ± 40.6 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

In [340]: %timeit df['a'].map(dict(zip(L2, L5))).fillna(df['a'])
54 ms ± 215 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

答案 1 :(得分:0)

您可以使用np.select,例如:

import numpy as np
condition = [df['a'] == i for i in L2]
df['a'] = np.select(condition, L5, df['a'])

您会得到:

    a   b
0   9  23
1  10  45
2  11  67
3  11  89
4  10   0
5   4  -1
6   5   2
7   6   3

计时:让我们创建一个更大的数据框,例如使用df

df_l = pd.concat([df]*10000)
print (df_l.shape)
(80000, 2)

现在有一些timeit

# with map, @jezrael
d = dict(zip(L2, L5))
%timeit  df_l['a'].map(d).fillna(df_l['a'])
100 loops, best of 3: 7.71 ms per loop
# with np.select
condition = [df_l['a'] == i for i in L2]
%timeit np.select(condition, L5, df_l['a'])
1000 loops, best of 3: 350 µs per loop