【问题标题】:Is there any function in python which can perform the inverse of numpy.repeat function?python中是否有任何函数可以执行numpy.repeat函数的逆运算?
【发布时间】:2016-08-02 13:38:32
【问题描述】:

例如

x = np.repeat(np.array([[1,2],[3,4]]), 2, axis=1)

给你

x = array([[1, 1, 2, 2],
          [3, 3, 4, 4]])

但是有什么可以执行的

 x = np.*inverse_repeat*(np.array([[1, 1, 2, 2],[3, 3, 4, 4]]), axis=1)

给你

x = array([[1,2],[3,4]])

【问题讨论】:

  • 您在说repeat 的通用性如何?您是否提前知道重复参数?在已知轴上重复单个数字很容易。但是 repeat 可以为每个元素使用不同的数字。
  • @hpaulj 正如我在问题中所说,我想要 np.repeat 函数的精确倒数。即固定重复次数
  • 查看我的回答,了解我为什么问这个问题的更多详细信息。

标签: python python-2.7 numpy


【解决方案1】:

常规切片应该可以工作。对于要反转重复的轴,请使用::number_of_repetitions

x = np.repeat(np.array([[1,2],[3,4]]), 4, axis=0)
x[::4, :]  # axis=0
Out: 
array([[1, 2],
       [3, 4]])

x = np.repeat(np.array([[1,2],[3,4]]), 3, axis=1)

x[:,::3]  # axis=1
Out: 
array([[1, 2],
       [3, 4]])


x = np.repeat(np.array([[[1],[2]],[[3],[4]]]), 5, axis=2)
x[:,:,::5]  # axis=2
Out: 
array([[[1],
        [2]],

       [[3],
        [4]]])

【讨论】:

  • 请注意,切片语法不允许我们轻松地以编程方式表达要重复的轴
【解决方案2】:

这应该可以工作,并且与 np.repeat 具有完全相同的签名:

def inverse_repeat(a, repeats, axis):
    if isinstance(repeats, int):
        indices = np.arange(a.shape[axis] / repeats, dtype=np.int) * repeats
    else:  # assume array_like of int
        indices = np.cumsum(repeats) - 1
    return a.take(indices, axis)

编辑:添加了对每项重复的支持,类似于 np.repeat

【讨论】:

  • take 的不错应用 - 比构建多轴切片元组更容易。
  • 是的;我在我的 numpy 职业生涯中很晚才学会了 take,每次回顾我试图以编程方式在给定轴上操作的旧代码时,我都会畏缩
【解决方案3】:

对于我们知道轴和重复的情况——并且重复是一个标量(所有元素的值相同),我们可以像这样构造一个切片索引:

In [1117]: a=np.array([[1, 1, 2, 2],[3, 3, 4, 4]])
In [1118]: axis=1; repeats=2

In [1119]: ind=[slice(None)]*a.ndim
In [1120]: ind[axis]=slice(None,None,a.shape[axis]//repeats)
In [1121]: ind
Out[1121]: [slice(None, None, None), slice(None, None, 2)]
In [1122]: a[ind]
Out[1122]: 
array([[1, 2],
       [3, 4]])

@Eelco's 使用 take 可以更轻松地专注于一个轴,但需要索引列表,而不是切片。

repeat 确实允许不同的重复计数。

In [1127]: np.repeat(a1,[2,3],axis=1)
Out[1127]: 
array([[1, 1, 2, 2, 2],
       [3, 3, 4, 4, 4]])

知道axis=1repeats=[2,3] 我们应该能够构建正确的take 索引(可能使用cumsum)。切片不起作用。

但如果我们只知道轴,而重复次数未知,那么我们可能需要某种uniqueset 操作,如@redratear's 答案。

In [1128]: a2=np.repeat(a1,[2,3],axis=1)
In [1129]: y=[list(set(c)) for c in a2]
In [1130]: y
Out[1130]: [[1, 2], [3, 4]]

带有列表repeatstake 解决方案。这应该选择每个重复块的最后一个:

In [1132]: np.take(a2,np.cumsum([2,3])-1,axis=1)
Out[1132]: 
array([[1, 2],
       [3, 4]])

已删除的答案使用unique;这是我逐行使用unique

In [1136]: np.array([np.unique(row) for row in a2])
Out[1136]: 
array([[1, 2],
       [3, 4]])

uniqueset 更好,因为它保持元素顺序。 unique (或设置)还有另一个问题 - 如果原件有重复值怎么办,例如[[1,2,1,3],[3,3,4,1]].

这是一个很难从结果中推断出重复模式的情况。我必须先查看所有行。

In [1169]: a=np.array([[2,1,1,3],[3,3,2,1]])
In [1170]: a1=np.repeat(a,[2,1,3,4], axis=1)
In [1171]: a1
Out[1171]: 
array([[2, 2, 1, 1, 1, 1, 3, 3, 3, 3],
       [3, 3, 3, 2, 2, 2, 1, 1, 1, 1]])

但是 cumsum 在已知的重复上很好地解决了它:

In [1172]: ind=np.cumsum([2,1,3,4])-1
In [1173]: ind
Out[1173]: array([1, 2, 5, 9], dtype=int32)
In [1174]: np.take(a1,ind,axis=1)
Out[1174]: 
array([[2, 1, 1, 3],
       [3, 3, 2, 1]])

【讨论】:

    【解决方案4】:
    >>> import numpy as np
    >>> x = np.repeat(np.array([[1,2],[3,4]]), 2, axis=1)
    >>> y=[list(set(c)) for c in x] #This part remove duplicates for each array in tuple. So this will not work for x = np.repeat(np.array([[1,1],[3,3]]), 2, axis=1)=[[1,1,1,1],[3,3,3,3]. Result will be [[1],[3]]
    >>> print y
    [[1, 2], [3, 4]]
    

    你不需要知道轴和重复量...

    【讨论】:

    • 虽然此代码可能有助于解决问题,但提供有关 why 和/或 如何 回答问题的额外上下文将显着改善其长期长期价值。请edit您的答案添加解释,包括适用的限制和假设。
    • 为什么你对这个答案的格式很挑剔,而不是其他的?在一般的重复情况下,可能需要某种setunique。不鼓励恢复到 numpy 中的列表理解,但有时是必需的。
    • 好的@TobySpeight 我会做任何你想做的事。对不起我的错误,因为我是新成员。我不知道一般规则。
    • @hpaul - 只是因为这是在评论中呈现给我的唯一答案。 FWIW,我不是反对者。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-03-04
    • 2020-11-24
    • 2014-08-20
    • 2011-02-23
    • 1970-01-01
    • 2023-01-08
    • 2019-03-24
    相关资源
    最近更新 更多