【问题标题】:Vectorization & ValueError, but not from "or" and "and" operatorsVectorization & ValueError,但不是来自“or”和“and”运算符
【发布时间】:2021-05-13 15:09:14
【问题描述】:

question and answer chain 很好地解释了如何解决使用条件时出现的 ValueErrors,例如“或”代替|,和“和”代替&。但我在该链中看不到任何解决“ValueError,Series 的真值不明确的问题。使用 a.empty、a.bool()、a.item()、a.any() 或a.all()" 用于向量化,当尝试将向量化与编写为将单个数字作为输入的函数一起使用时。

具体来说,在这种情况下,Map 和 Apply 可以正常工作,但 Vectorization 仍然会抛出 ValueError。

下面的代码,有人可以分享如何解决这个问题,以便可以在不修改函数(或不过多修改函数)的情况下使用矢量化?谢谢!


代码:

# import numpy and pandas, create dataframe.
import numpy as np
import pandas as pd
x = range(1000)
df = pd.DataFrame(data = x, columns = ['Number']) 

# define simple function to return True or False if number passed in is prime
def is_prime(num):
    if num < 2:
        return False
    elif num == 2: 
        return True
    else: 
        for i in range(2,num):
            if num % i == 0:
                return False
    return True

# Call various ways of applying the function to the data frame
df['map prime'] = list(map(is_prime, df['Number']))
df['apply prime'] = df['Number'].apply(is_prime)

# look at dataframe
in: df.head()
out: Number     map prime   apply prime
0   0   264     False       False
1   1   907     False       False
2   2   354     True        True
3   3   583     True        True
4   4   895     False       False

# now try to vectorizing
in: df['optimize prime'] = is_prime(df['Number'])
out: ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().

【问题讨论】:

  • 您的 if/else 表达式与 or/and 存在相同的问题 - 它们都需要一个简单的 True/False 值。
  • 有没有简单的方法来解决这个问题,比如用 | 替换“或”或“和”与 &?
  • &lt;2==2 测试很容易用掩码代替。但是elserange(2,num) 上有一个循环,其中num 只能是一个标量。此外嵌套的if 短路。将此应用于整个系列,需要对任务进行重大的重新可视化。

标签: python pandas numpy vectorization apply


【解决方案1】:

你可以试试 numpy 的 vectorize:

vis_prime = np.vectorize(is_prime)

df['optimize prime'] = vis_prime(df['Number'])

这给了你:

   Number  map prime  apply prime  optimize prime
0       0      False        False           False
1       1      False        False           False
2       2       True         True            True
3       3       True         True            True
4       4      False        False           False

【讨论】:

【解决方案2】:
In [133]: timeit df['map prime'] = list(map(is_prime, df['Number']))
6.25 ms ± 65.8 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
In [134]: timeit df['apply prime'] = df['Number'].apply(is_prime)
6.18 ms ± 27.9 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

np.vectorize 有一个重要的免责声明——它不是性能工具

In [137]: timeit df['optimize prime'] = vis_prime(df['Number'])
5.83 ms ± 7.28 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

它并不比 pandas 自己的 apply 迭代器快多少。

还有一个简单的列表理解:

In [140]: timeit [is_prime(num) for num in x]
5.65 ms ± 10 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

要获得真正的“矢量化”加速,我们必须编写适用于整个数组的代码,或者在本例中是一个系列。

此函数具有固有的串行质量。特别是

        if num % i == 0:
            return False

短路,无需遍历整个range(2,num)。一些初筛也建立在以前的num

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-02-26
  • 2014-09-08
  • 2020-12-17
  • 2021-01-09
  • 1970-01-01
相关资源
最近更新 更多