首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Numpy:用numpy数组替换numpy数组中的零

Numpy:用numpy数组替换numpy数组中的零
EN

Stack Overflow用户
提问于 2018-11-23 17:11:57
回答 3查看 1K关注 0票数 2

处理我想要处理的数据。请注意,我只限于矮胖,不能使用熊猫。原始数据如下:

代码语言:javascript
复制
data = [
  [ 1, a, [<metric1>, <metric2>] ],
  [ 1, b, [<metric1>, <metric2>] ],
  [ 2, b, [<metric1>, <metric2>] ],
  [ 2, c, [<metric1>, <metric2>] ],
  [ 3, a, [<metric1>, <metric2>] ],
  [ 3, c, [<metric1>, <metric2>] ],
  ...etc
]

用numpy旋转我的数据:

代码语言:javascript
复制
rows, row_pos = np.unique(data[:, row_index], return_inverse=True)
cols, col_pos = np.unique(data[:, col_index], return_inverse=True)
pivot_table = np.zeros((len(rows), len(cols)), dtype=object)
pivot_table[row_pos, col_pos] = data[:, pivot_index]

由此产生的格式是:

代码语言:javascript
复制
cols = [a, b, c, ...]
rows = [1, 2, 3, ...]
pivot_table = [
  [ [<metric1>, <metric2>], [<metric1>, <metric2>], 0, ... ],
  [ 0, [<metric1>, <metric2>], [<metric1>, <metric2>], ... ],
  [ [<metric1>, <metric2>], 0, [<metric1>, <metric2>], ... ],
  ...
]

旋转表最终会呈现出来,它会记录零的位置,并将创建正确的单元格数,从而使表的格式正确。

这只是一个临时的解决办法,因为我最初尝试用numpy数组(即0,0)替换零。

代码语言:javascript
复制
pivot_table[pivot_table == 0] = [0,0]

但我得到了以下错误:

代码语言:javascript
复制
TypeError: NumPy boolean array indexing assignment requires a 0 or 1-dimensional input, input has 2 dimensions

我的临时修复已经足够了,但是当我想要做一些事情,比如有一行列和时,就会受到限制。我有许多方法,但不知道如何执行:

  1. 如前所述,将事实后的零替换为零列表。
  2. 当最初使用来自np.unique的索引创建表时,有一个默认值来填充表,而不是零。
  3. 将度量从列表中提取到数组中,即[ 1, a, <metric1>, <metric2> ]。这可能是简化聚合函数的最佳解决方案。

上述任何一种方法都有解决办法吗?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2018-11-23 18:54:05

试图重现你的案子:

代码语言:javascript
复制
In [182]: a,b,c = 0,1,2
In [183]: metric1, metric2 = 100,200
In [186]: data = [
     ...:   [ 1, a, [metric1, metric2] ],
     ...:   [ 1, b, [metric1, metric2] ],
     ...:   [ 2, b, [metric1, metric2] ],
     ...:   [ 2, c, [metric1, metric2] ],
     ...:   [ 3, a, [metric1, metric2] ],
     ...:   [ 3, c, [metric1, metric2] ],
     ...: ]
In [187]: 
In [187]: data
Out[187]: 
[[1, 0, [100, 200]],
 [1, 1, [100, 200]],
 [2, 1, [100, 200]],
 [2, 2, [100, 200]],
 [3, 0, [100, 200]],
 [3, 2, [100, 200]]]

In [189]: data = np.array(data,object)
In [190]: rows, row_pos = np.unique(data[:, 0], return_inverse=True)
     ...: cols, col_pos = np.unique(data[:, 1], return_inverse=True)
     ...: pivot_table = np.zeros((len(rows), len(cols)), dtype=object)

In [191]: pivot_table
Out[191]: 
array([[0, 0, 0],
       [0, 0, 0],
       [0, 0, 0]], dtype=object)
In [192]: pivot_table[row_pos, col_pos] = data[:, 2]
In [193]: pivot_table
Out[193]: 
array([[list([100, 200]), list([100, 200]), 0],
       [0, list([100, 200]), list([100, 200])],
       [list([100, 200]), 0, list([100, 200])]], dtype=object)
In [194]: pivot_table[row_pos, col_pos]
Out[194]: 
array([list([100, 200]), list([100, 200]), list([100, 200]),
       list([100, 200]), list([100, 200]), list([100, 200])], dtype=object)
In [195]: _.shape
Out[195]: (6,)
In [196]: data[:,2].shape
Out[196]: (6,)

此赋值在源形状(和dtype)之间工作,与目标的(6,)匹配。

代码语言:javascript
复制
In [197]: mask = pivot_table==0
In [198]: mask
Out[198]: 
array([[False, False,  True],
       [ True, False, False],
       [False,  True, False]])
In [199]: pivot_table[mask]
Out[199]: array([0, 0, 0], dtype=object)
In [200]: pivot_table[mask] = [0,0]
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-200-83e0a7422802> in <module>()
----> 1 pivot_table[mask] = [0,0]

ValueError: NumPy boolean array indexing assignment cannot assign 2 input values to the 3 output values where the mask is true

不同的错误信息(不同的numpy版本?),但这说明我试图将2个值放入3个插槽中。它并不将[0,0]作为一个单独的项目,而是作为2。

分配标量元素没有问题:

代码语言:javascript
复制
In [203]: pivot_table[mask] = None
In [204]: pivot_table
Out[204]: 
array([[list([100, 200]), list([100, 200]), None],
       [None, list([100, 200]), list([100, 200])],
       [list([100, 200]), None, list([100, 200])]], dtype=object)

在过去,我曾成功地使用frompyfunc创建对象dtype数组。定义一个小函数。我本来可以测试0或类型,但既然我已经没有插入任何内容,那么让我们来测试一下:

代码语言:javascript
复制
In [205]: def fun(x):
     ...:     if x is None: return [0,0]
     ...:     return x

将其应用于pivot_table的每个元素,生成一个新的数组。

代码语言:javascript
复制
In [230]: arr1 = np.frompyfunc(fun,1,1)(pivot_table)
In [231]: arr1
Out[231]: 
array([[list([100, 200]), list([100, 200]), list([0, 0])],
       [list([0, 0]), list([100, 200]), list([100, 200])],
       [list([100, 200]), list([0, 0]), list([100, 200])]], dtype=object)

另一种方法,让我们尝试分配一个列表:

代码语言:javascript
复制
In [240]: pivot_table[mask] = [[0,0] for _ in range(3)]    
TypeError: NumPy boolean array indexing assignment requires a 0 or 1-dimensional input, input has 2 dimensions

但是,如果我在where上尝试同样的方法,它就会奏效:

代码语言:javascript
复制
In [241]: pivot_table[np.where(mask)] = [[0,0] for _ in range(3)]
In [242]: pivot_table
Out[242]: 
array([[list([100, 200]), list([100, 200]), list([0, 0])],
       [list([0, 0]), list([100, 200]), list([100, 200])],
       [list([100, 200]), list([0, 0]), list([100, 200])]], dtype=object)

有了where,它更像是你最初分配给pivot_table的任务。

代码语言:javascript
复制
In [243]: np.where(mask)
Out[243]: (array([0, 1, 2]), array([2, 0, 1]))

这种数组索引仍然存在广播问题,

代码语言:javascript
复制
In [244]: pivot_table[np.where(mask)] = [0,0]
ValueError: cannot copy sequence with size 2 to array axis with dimension 3

通常布尔掩码索引的行为类似于等价的np.where(mask)索引,但在这里,显然,对象dtype的相互作用,以及广播与布尔索引的混乱。

Out[231]仍然是一个(3,3)数组,尽管所有元素都是len 2列表。要将其转换为数字数组,我们必须执行以下操作:

代码语言:javascript
复制
In [248]: p = np.stack(pivot_table.ravel()).reshape(3,3,2)
In [249]: p
Out[249]: 
array([[[100, 200],
        [100, 200],
        [  0,   0]],

       [[  0,   0],
        [100, 200],
        [100, 200]],

       [[100, 200],
        [  0,   0],
        [100, 200]]])

np.concatenate (和*stack版本)可以将列表连接到数组中,但是它必须从列表或平面数组开始,因此需要进行ravel和reshape。

np.array(pivot_table.tolist())也能工作。

如果您构建了一个结构化数据数组(假设metric值是数字的):

代码语言:javascript
复制
In [265]: data1 = np.array([tuple(x.tolist()) for x in data],'i,i,2i')
In [266]: data1
Out[266]: 
array([(1, 0, [100, 200]), (1, 1, [100, 200]), (2, 1, [100, 200]),
       (2, 2, [100, 200]), (3, 0, [100, 200]), (3, 2, [100, 200])],
      dtype=[('f0', '<i4'), ('f1', '<i4'), ('f2', '<i4', (2,))])
In [267]: data1['f2']
Out[267]: 
array([[100, 200],
       [100, 200],
       [100, 200],
       [100, 200],
       [100, 200],
       [100, 200]], dtype=int32)

这些值可以分配给3d pivot_table:

代码语言:javascript
复制
In [268]: p = np.zeros((len(rows), len(cols),2),int)
In [269]: p[row_pos, col_pos]=data1['f2']

使用Panzer定义的fillvalue数组,您的初始蒙面任务可以工作:

代码语言:javascript
复制
In [322]: fillvalue = np.empty((), 'O')
     ...: fillvalue[()] = [0, 0]
     ...: 
In [323]: fillvalue
Out[323]: array(list([0, 0]), dtype=object)
In [324]: mask
Out[324]: 
array([[False, False,  True],
       [ True, False, False],
       [False,  True, False]])
In [325]: pivot_table[mask] = fillvalue

他的fullnp.copyto(a, fill_value, casting='unsafe'),我们的蒙面作业可以写成:np.copyto(pivot_table, fillvalue, where=mask)

票数 2
EN

Stack Overflow用户

发布于 2018-11-23 20:31:49

下面是如何让您的方法2开始工作:

代码语言:javascript
复制
fillvalue = np.empty((), 'O')
fillvalue[()] = [0, 0]
pivot_table = np.full((len(rows), len(cols)), fillvalue)

etc.

请注意,[0, 0]都是相同的对象,所以如果您想要更改其中的一个对象,您不应该通过修改list对象来完成它,而是创建一个新的列表并将其分配给数组位置。

如果您想要一个3D数字数组而不是一个列表数组,那么快速修复就是np.array(pivot_table.tolist())

票数 2
EN

Stack Overflow用户

发布于 2018-11-23 19:12:35

您的输入数据类型不清楚,可能会造成不便。避免对象类型,便于数据结构分析。使用结构化数组可以帮助:

原始数据样本:

代码语言:javascript
复制
n=10
data= [ [randint(5),'abcdef'[randint(6)],rand(2)] for _ in range(n)]

手工打字和填写:

代码语言:javascript
复制
dt=np.dtype([('i', 'i4'), ('j', 'U1'), ('val', 'f8', 2)])
arr = ndarray(len(data),dtype=dt)
for k,(a,b,c) in enumerate (data):
    arr[k]['i']=a
    arr[k]['j']=b
    arr[k]['val']=c

现在一切都很简单:

代码语言:javascript
复制
row=arr['i']
col=arr['j']
val=arr['val']

(r,ri),(c,ci) = (np.unique(x,return_inverse=True) for x in (row,col))
res=zeros((len(r),len(c),2)) # the good shape
res[ri,ci]=val

res现在

代码语言:javascript
复制
[[[ 0.87  0.96]
  [ 0.03  0.92]
  [ 0.45  0.55]
  [ 0.    0.  ]
  [ 0.    0.  ]]

 [[ 0.27  0.84]
  [ 0.    0.  ]
  [ 0.41  0.05]
  [ 0.47  0.67]
  [ 0.    0.  ]]

 [[ 0.3   0.05]
  [ 0.    0.  ]
  [ 0.    0.  ]
  [ 0.    0.  ]
  [ 0.37  0.76]]

 [[ 0.    0.  ]
  [ 0.    0.  ]
  [ 0.    0.  ]
  [ 0.    0.  ]
  [ 0.4   0.07]]]
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53450669

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档