熊猫`在df.index`中尝试df.loc [x]`vs`x

时间:2014-05-13 23:54:54

标签: python pandas

我有一个包含一列的数据框。我想编写一个函数来返回给定键值的列值;如果密钥不在索引中,则为不同的(常量)值。我能想到(至少)两种合理的方法来实现这一点 - 除了速度之外,是否有理由比另一种更好?

并且w / r / t速度,len(df)= 10k且len(ids_to_check)= 20k,try / except大约慢2倍。这对我来说是令人惊讶的,因为另一种方法必须遍历索引两次。 对此行为有任何直观的解释吗?

  1. 使用try / except

    def attempt_1(id_val,df):
        try:
            return df.loc[id_val]
        except KeyError:
            return constant_val
    
    %timeit [attempt_1(i,df) for i in ids_to_check]
    
    1 loops, best of 3: 480 ms per loop
    
  2. 使用in来测试id_val是否在索引中

    def attempt_2(id_val,df):
        if id_val in df.index:
            return df.loc[id_val]
        else:
            return constant_val
    
    %timeit [attempt_2(i,df) for i in ids_to_check]
    
    1 loops, best of 3: 235 ms per loop
    

1 个答案:

答案 0 :(得分:0)

创建测试框架

In [22]: df = DataFrame(dict(A = np.random.randn(10000)))                            

选择一些ID

In [21]: ids_to_check = np.random.choice(np.arange(0,20000),size=10000,replace=False)

你的方法

In [18]: %timeit [attempt_2(i,df) for i in ids_to_check]
1 loops, best of 3: 409 ms per loop

In [16]: %timeit [attempt_1(i,df) for i in ids_to_check]
1 loops, best of 3: 620 ms per loop

使用矢量化查找的有效方法。如果位置值在索引中,则isin返回一个布尔数组;索引这个很快。

然后我重新索引以恢复原始索引并填充缺失条目的值

In [19]: %timeit df.A.loc[df.index.isin(ids_to_check)].reindex(df.index).fillna(-100)
100 loops, best of 3: 6.74 ms per loop

这会返回一个系列;很容易就可以返回DataFrame

In [20]: df.A.loc[df.index.isin(np.random.choice(np.arange(0,20000),size=10000,replace=False))].reindex(df.index).fillna(-100)
Out[20]: 
0    -100.000000
1      -0.485421
2      -0.397338
3    -100.000000
4       0.573031
5    -100.000000
6       0.359699
7       0.298462
8    -100.000000
9      -1.274819
10   -100.000000
11      0.112869
12   -100.000000
13     -2.251186
14     -0.846211
...
9985   -100.000000
9986     -0.988055
9987     -0.080460
9988   -100.000000
9989      1.007490
9990     -1.454466
9991      0.875455
9992   -100.000000
9993   -100.000000
9994      0.194506
9995   -100.000000
9996   -100.000000
9997   -100.000000
9998     -0.477828
9999     -0.777487
Name: A, Length: 10000, dtype: float64

所以答案总是使用矢量化方法,永远不要循环。