在Python3中工作。
假设您有一百万只甲虫,您的任务是对它们的斑点大小进行分类。因此,您将创建一个表格,其中每一行都是甲虫,行中的数字代表斑点的大小;
[[.3, 1.2, 0.5],
[.6, .7],
[1.4, .9, .5, .7],
[.2, .3, .1, .7, .1]]
此外,您决定将其存储在一个numpy数组中,为此您用None填充列表(numpy会将其转换为np.nan)。
[[.3, 1.2, 0.5, None, None],
[.6, .7, None, None, None],
[1.4, .9, .5, .7, None],
[.2, .3, .1, .7, .1]]
但是有一个问题,由于3个原因之一,表示为None的值可以为None;
甲虫没有很多斑点;该数量不存在。
甲虫不会静止不动,也无法测量斑点。
您还没有全面测量那只甲虫的信息,因此该值尚未分配。
我的问题实际上并不涉及甲虫,但是原理是相同的。 我想要3个不同的None值,这样我就可以使这些缺失值的原因保持明显。我当前的解决方案是使用一个太大的值,从物理上讲不可能,但这并不是一个非常安全的解决方案。
假设您不能使用负数-实际上,我要测量的数量可能是负数。
数据很大,读取速度很重要。
编辑;正确的评论指出,说速度很重要,而不说什么操作没有意义。主成分分析可能将用于变量去相关,聚类算法的欧几里德距离平方计算(但该变量中的数据稀疏)可能需要一些插值。最终是递归神经网络,但这将来自库,因此我只需要将数据转换为输入形式即可。因此,也许没有什么比线性代数更糟糕的了,如果我仔细考虑的话,它们应该都适合RAM。
什么是好的策略?
答案 0 :(得分:5)
最简单的方法是使用字符串:“不计算”,“未知”和“不适用”。但是,如果要以numpy快速处理,则混合数字/对象的数组不是您的朋友。
我的建议是添加几个与数据形状相同的数组,由0和1组成。因此,数组missing
= 1,其中点缺失,否则为0,依此类推,与数组{ {1}}等。
然后,您可以在任何地方使用NaN,然后用not_measured
屏蔽数据,以轻松找到所需的特定NaN。
答案 1 :(得分:3)
如果只需要一个未知值也不为class MyCreateView(LoginRequiredMixin, generic.CreateView):
def form_valid(self, form):
form.instance.owner = self.request.user
return super().form_valid(form)
的对象,只需创建一个新对象:
None
现在,您可以像使用NOT_APPLICABLE = object()
NOT_MEASURED = object()
UNKNOWN = object()
一样使用这些值:
None
等
如果您需要一个可以表示为[1.4, .9, .5, .7, UNKNOWN]
...
if value is UNKNOWN:
# do something
的值(例如,在float
数组中),则可以使用尾数编码的“额外”数据创建一个NaN值。但是,这样做可能不是安全,因为不能保证通过对值的各种操作来保留这些位。
答案 2 :(得分:3)
以下是一种解决方案(免责声明:HACK!),可以避免诸如对象dtype或单独的遮罩之类的减速带:
nan
的fp表示周围似乎有很多“死角”:
>>> nan_as_int = np.array(np.nan).view(int)[()]
>>> nan_as_int
9221120237041090560
>>> custom_nan = np.arange(nan_as_int, nan_as_int+10).view(float)
>>> custom_nan
array([nan, nan, nan, nan, nan, nan, nan, nan, nan, nan])
我们创建了十个不同的nan
。请注意,这与使用float("nan")
创建多个实例不同。这些实例将全部映射到numpy中的相同值,因此一旦放入非对象数组中就无法区分。
即使我们的十个nan
具有不同的表示形式,但在浮点级别也很难区分(因为每个定义nan != nan
甚至对于唯一的nan
也是如此)。所以我们需要一个小帮手:
>>> def which_nan(a):
... some_nan = np.isnan(a)
... return np.where(some_nan, np.subtract(a.view(int), nan_as_int, where=some_nan), -1)
示例:
>>> exmpl = np.array([0.1, 1.2, custom_nan[3], custom_nan[0]])
>>> exmpl
array([0.1, 1.2, nan, nan])
>>> which_nan(exmpl)
array([-1, -1, 3, 0], dtype=int64)
也许令人惊讶的是,这似乎在至少一些基本的numpy操作中仍然存在:
>>> which_nan(np.sin(exmpl))
array([-1, -1, 3, 0], dtype=int64)
答案 3 :(得分:2)
在以下问题的评论中,我问为什么不使用np.inf
,-np.inf
和np.nan
,作者回答这就是他所需要的。
所以我添加了帖子,因为人们更多地关注回复而不是评论。
答案 4 :(得分:1)
建议为每个案例创建三个不同的object
实例。
由于您希望这些对象具有NaN
的属性,因此您可以尝试创建三个不同的NaN
实例。
NOT_APPLICABLE = float("nan")
NOT_MEASURED = float("nan")
UNKNOWN = float("nan")
这是被黑客攻击的极限,因此使用后果自负,但我相信任何Python实现都不会NaN
来优化以始终重复使用同一对象。尽管如此,您仍可以添加哨兵条件以在运行前进行检查。
if NOT_APPLICABLE is NOT_MEASURED or NOT_MEASURED is UNKNOWN or UNKNOWN is NOT_APPLICABLE :
raise ValueError # or try something else
如果此方法有效,则可以让您比较NaN
id以检查其含义。
row = [1.0, 2.4, UNKNOWN]
...
if value is UNKNOWN:
...
同时,它保留了numpy
可能对其数组进行的任何优化。
披露:这是一个不明智的建议,我很想听听其他人的消息。