【问题标题】:Python: Counting identical rows in an array (without any imports)Python:计算数组中相同的行(没有任何导入)
【发布时间】:2014-03-03 21:18:27
【问题描述】:

例如,给定:

import numpy as np
data = np.array(
    [[0, 0, 0],
    [0, 1, 1],
    [1, 0, 1],
    [1, 0, 1],
    [0, 1, 1],
    [0, 0, 0]])

我想得到一个 3 维数组,看起来像:

result = array([[[ 2.,  0.],
                 [ 0.,  2.]],

                [[ 0.,  2.],
                 [ 0.,  0.]]])

一种方法是:

for row in data
    newArray[ row[0] ][ row[1] ][ row[2] ] += 1

我想要做的是:

for i in dimension1
   for j in dimension2
      for k in dimension3
          result[i,j,k] = (data[data[data[:,0]==i, 1]==j, 2]==k).sum()

这似乎不起作用,我想通过坚持我的实现而不是一开始提到的实现(或使用任何额外的导入,例如计数器)来达到预期的结果。

谢谢。

【问题讨论】:

  • 我相信你使用的是 numpy。
  • 是的,没错,会修复它。无论如何,有什么想法吗?
  • 我认为您的第一种方法更容易阅读,当然也更快。
  • @tobias_k 我知道!我只是想知道为什么第二种方法不起作用:)
  • 请下次发布语法正确的代码

标签: python arrays list numpy


【解决方案1】:

不要害怕进口。它们使 Python 变得很棒。

如果问题假设您已经有了结果矩阵。

import numpy as np
data = np.array(
    [[0, 0, 0],
     [0, 1, 1],
     [1, 0, 1],
     [1, 0, 1],
     [0, 1, 1],
     [0, 0, 0]]
)
result = np.zeros((2,2,2))

# range of each dim, aka allowable values for each dim
dim_ranges = zip(np.zeros(result.ndim), np.array(result.shape)-1)
dim_ranges
# Out[]:
#     [(0.0, 2), (0.0, 2), (0.0, 2)]

# Multidimentional histogram will effectively "count" along each dim
sums,_ = np.histogramdd(data,bins=result.shape,range=dim_ranges)
result += sums
result
# Out[]:
#     array([[[ 2.,  0.],
#             [ 0.,  2.]],
#
#            [[ 0.,  2.],
#             [ 0.,  0.]]])

此解决方案可解决任何“结果”ndarray,无论其形状如何。此外,即使您的“数据”ndarray 具有超出结果矩阵范围的索引,它也可以正常工作。

【讨论】:

    【解决方案2】:

    问题是data[data[data[:,0]==i, 1]==j, 2]==k 不是你所期望的。

    让我们把这个拆开看(i,j,k) == (0,0,0)这个案子

    data[:,0]==0 是 [True, True, False, False, True, True],data[data[:,0]==0] 正确地给出了第一个数字是 0 的行。

    现在从这些行我们得到第二个数字是0的行:data[data[:,0]==0, 1]==0,这给了我们[True, False, False, True]。这就是问题所在。因为如果我们从data 获取这些索引,即data[data[data[:,0]==0, 1]==0],我们不会得到第一个和第二个数字是0 的行,而是0th 和3rd 行:

    In [51]: data[data[data[:,0]==0, 1]==0]
    Out[51]: array([[0, 0, 0],
                    [1, 0, 1]])
    

    如果我们现在过滤第三个数字是 0 的行,我们会得到错误的结果 w.r.t。原始数据。

    这就是为什么你的方法行不通的原因。有关更好的方法,请参阅其他答案。

    【讨论】:

      【解决方案3】:

      您也可以为此使用numpy.histogramdd:

      >>> np.histogramdd(data, bins=(2, 2, 2))[0]
      array([[[ 2.,  0.],
              [ 0.,  2.]],
      
             [[ 0.,  2.],
              [ 0.,  0.]]])
      

      【讨论】:

        【解决方案4】:

        您可以执行以下操作

        #Get output dimension and construct output array.
        >>> dshape = tuple(data.max(axis=0)+1)
        >>> dshape
        (2, 2, 2)
        >>> out = np.zeros(shape)
        

        如果你有 numpy 1.8+:

        out.flat[np.ravel_multi_index(data.T, dshape)]+=1
        

        其他:

        #Get indices and unique the resulting array
        >>> inds = np.ravel_multi_index(data.T, dshape)
        >>> inds, inverse = np.unique(inds, return_inverse=True)
        >>> values = np.bincount(inverse)
        
        >>> values
        array([2, 2, 2])
        
        >>> out.flat[inds] = values
        >>> out
        array([[[ 2.,  0.],
                [ 0.,  2.]],
        
               [[ 0.,  2.],
                [ 0.,  0.]]])
        

        numpy 1.7 之前的 Numpy 版本没有 add.at 属性,没有它,顶部代码将无法工作。由于ravel_multi_index 可能不是您可以考虑采用 numpy 数组的unique rows 的最快算法。实际上这两个操作应该是等价的。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2017-12-28
          • 1970-01-01
          • 2022-11-15
          • 1970-01-01
          • 1970-01-01
          • 2013-08-05
          • 1970-01-01
          相关资源
          最近更新 更多