为什么 np.vectorize 在 np.where 抛出 TypeError 时在这里工作?
why does np.vectorize work here when np.where throws a TypeError?
我有一个 pandas DataFrame,其中名为 myenum 的列的值为 0、1 或 2。我正在尝试将 1 和 2 转换为字符串并使用 Enum 的 .name 属性来提供帮助。
我认为这是一个关于理解 np.where 与 np.vectorize 的核心的问题,因为它们与 DataFrame 系列相关。我很好奇为什么尝试使用 np.where 时会引发错误,但使用 np.vectorize 时却可以正常工作。我想从中学习并更好地理解 DataFrames 中的最佳矢量化实践。
import enum
import numpy as np
import pandas as pd
df = pd.DataFrame() # one column in this df is 'myenum', its values are either 0, 1, or 2
df['myenum'] = [0, 1, 2, 0, 0, 0, 2, 1, 0]
class MyEnum(enum.Enum):
First = 1
Second = 2
# this throws a TypeError - why?
df['myenum'] = np.where(
df['myenum'] > 0,
MyEnum(df['myenum']).name,
''
)
# whereas this, which seems pretty analagous, works. what am i missing?
def vectorize_enum_value(x):
if x > 0:
return MyEnum(x).name
return ''
vect = np.vectorize(vectorize_enum_value)
df['myenum'] = vect(df['myenum'])
您的 where
表达式中的 完整回溯 是:
Traceback (most recent call last):
File "/usr/lib/python3.8/enum.py", line 641, in __new__
return cls._value2member_map_[value]
TypeError: unhashable type: 'Series'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "<ipython-input-27-16f5edc71240>", line 3, in <module>
MyEnum(df['myenum']).name,
File "/usr/lib/python3.8/enum.py", line 339, in __call__
return cls.__new__(cls, value)
File "/usr/lib/python3.8/enum.py", line 648, in __new__
if member._value_ == value:
File "/usr/local/lib/python3.8/dist-packages/pandas/core/generic.py", line 1537, in __nonzero__
raise ValueError(
ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
将整个系列交给MyEnum
制作:
In [30]: MyEnum(df['myenum'])
Traceback (most recent call last):
File "/usr/lib/python3.8/enum.py", line 641, in __new__
return cls._value2member_map_[value]
TypeError: unhashable type: 'Series'
...
问题根本不在于 where
。
如果我们为它提供有效的字符串列表,where
工作正常:
In [33]: np.where(
...: df['myenum'] > 0,
...: [vectorize_enum_value(x) for x in df['myenum']],
...: ''
...: )
Out[33]:
array(['', 'First', 'Second', '', '', '', 'Second', 'First', ''],
dtype='<U6')
即第二个参数,列表理解与vectorize
基本相同。
where
是一个函数; Python 在传入函数参数之前对其进行评估。因此每个参数都必须有效。 where
是 不是 迭代器,就像 apply
甚至 vectorize
.
我有一个 pandas DataFrame,其中名为 myenum 的列的值为 0、1 或 2。我正在尝试将 1 和 2 转换为字符串并使用 Enum 的 .name 属性来提供帮助。
我认为这是一个关于理解 np.where 与 np.vectorize 的核心的问题,因为它们与 DataFrame 系列相关。我很好奇为什么尝试使用 np.where 时会引发错误,但使用 np.vectorize 时却可以正常工作。我想从中学习并更好地理解 DataFrames 中的最佳矢量化实践。
import enum
import numpy as np
import pandas as pd
df = pd.DataFrame() # one column in this df is 'myenum', its values are either 0, 1, or 2
df['myenum'] = [0, 1, 2, 0, 0, 0, 2, 1, 0]
class MyEnum(enum.Enum):
First = 1
Second = 2
# this throws a TypeError - why?
df['myenum'] = np.where(
df['myenum'] > 0,
MyEnum(df['myenum']).name,
''
)
# whereas this, which seems pretty analagous, works. what am i missing?
def vectorize_enum_value(x):
if x > 0:
return MyEnum(x).name
return ''
vect = np.vectorize(vectorize_enum_value)
df['myenum'] = vect(df['myenum'])
您的 where
表达式中的 完整回溯 是:
Traceback (most recent call last):
File "/usr/lib/python3.8/enum.py", line 641, in __new__
return cls._value2member_map_[value]
TypeError: unhashable type: 'Series'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "<ipython-input-27-16f5edc71240>", line 3, in <module>
MyEnum(df['myenum']).name,
File "/usr/lib/python3.8/enum.py", line 339, in __call__
return cls.__new__(cls, value)
File "/usr/lib/python3.8/enum.py", line 648, in __new__
if member._value_ == value:
File "/usr/local/lib/python3.8/dist-packages/pandas/core/generic.py", line 1537, in __nonzero__
raise ValueError(
ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
将整个系列交给MyEnum
制作:
In [30]: MyEnum(df['myenum'])
Traceback (most recent call last):
File "/usr/lib/python3.8/enum.py", line 641, in __new__
return cls._value2member_map_[value]
TypeError: unhashable type: 'Series'
...
问题根本不在于 where
。
如果我们为它提供有效的字符串列表,where
工作正常:
In [33]: np.where(
...: df['myenum'] > 0,
...: [vectorize_enum_value(x) for x in df['myenum']],
...: ''
...: )
Out[33]:
array(['', 'First', 'Second', '', '', '', 'Second', 'First', ''],
dtype='<U6')
即第二个参数,列表理解与vectorize
基本相同。
where
是一个函数; Python 在传入函数参数之前对其进行评估。因此每个参数都必须有效。 where
是 不是 迭代器,就像 apply
甚至 vectorize
.