【问题标题】:R function rep() in Python (replicates elements of a list/vector)Python中的R函数rep()(复制列表/向量的元素)
【发布时间】:2020-12-03 01:14:43
【问题描述】:

R 函数 rep() 复制向量的每个元素:

> rep(c("A","B"), times=2)
[1] "A" "B" "A" "B"

这就像 Python 中的列表乘法:

>>> ["A","B"]*2
['A', 'B', 'A', 'B']

但是使用 rep() R 函数也可以指定向量的每个元素的重复次数:

> rep(c("A","B"), times=c(2,3))
[1] "A" "A" "B" "B" "B"

在 Python 中有这样的函数吗?不然怎么定义呢?顺便说一句,我也对这种用于复制数组行的函数感兴趣。

【问题讨论】:

    标签: python


    【解决方案1】:

    使用numpy 数组和numpy.repeat 函数:

    import numpy as np
    
    x = np.array(["A", "B"])
    print np.repeat(x, [2, 3], axis=0)
    
    ['A' 'A' 'B' 'B' 'B']
    

    【讨论】:

      【解决方案2】:

      不确定是否有可用的内置功能,但您可以尝试以下方法:

      >>> lis = ["A", "B"]
      >>> times = (2, 3)
      >>> sum(([x]*y for x,y in zip(lis, times)),[])
      ['A', 'A', 'B', 'B', 'B']
      

      请注意,sum() 在二次时间中运行。所以,这不是推荐的方式。

      >>> from itertools import chain, izip, starmap
      >>> from operator import mul
      >>> list(chain.from_iterable(starmap(mul, izip(lis, times))))
      ['A', 'A', 'B', 'B', 'B']
      

      时间对比:

      >>> lis = ["A", "B"] * 1000
      >>> times = (2, 3) * 1000
      >>> %timeit list(chain.from_iterable(starmap(mul, izip(lis, times))))
      1000 loops, best of 3: 713 µs per loop
      >>> %timeit sum(([x]*y for x,y in zip(lis, times)),[])
      100 loops, best of 3: 15.4 ms per loop
      

      【讨论】:

      • 我认为如果您直接删除无论如何都不应该使用的sum(...) 解决方案,答案会更好。我想指出izip(lis, times) 仅在输入列表包含字符串时才有效。像lis = [1, 2] 这样的输入中的不可迭代会导致崩溃。你应该只使用itertools.repeat 而不是mul
      【解决方案3】:

      既然你说“数组”并提到 R。你可能还是想使用 numpy 数组,然后使用:

      import numpy as np
      np.repeat(np.array([1,2]), [2,3])
      

      编辑:既然你提到你也想重复行,我认为你应该使用 numpy. np.repeat 有一个轴参数来执行此操作。

      除此之外,也许:

      from itertools import izip, chain, repeat
      list(chain(*(repeat(a,b) for a, b in izip([1,2], [2,3]))))
      

      因为它没有假设你有一个列表或字符串要相乘。虽然我承认,将所有内容作为参数传递到链中可能并不完美,所以编写自己的迭代器可能会更好。

      【讨论】:

        【解决方案4】:
        l = ['A','B']
        n = [2, 4]
        

        您的示例使用了已经是可迭代的字符串。 您可以生成类似于列表的结果字符串。

        ''.join([e * m for e, m in zip(l, n)])
        'AABBBB'
        

        更新:这里不需要列表推导:

        ''.join(e * m for e, m in zip(l, n))
        'AABBBB'
        

        【讨论】:

        • @AshwiniChaudhary 正确...对于您的解决方案 - 但正如我在上面写的那样,我建议使用字符串而不是列表
        • 但是你可以跳过列表理解部分,直接使用:''.join(e * m for e, m in zip(l, n))
        【解决方案5】:

        你怎么看这种方式?

        重复一个值:

        >>> repetitions=[]
        >>> torep=3
        >>> nrep=5
        >>> for i in range(nrep):
        >>>     i=torep
        >>>     repetitions.append(i)
        [3, 3, 3, 3, 3]
        

        重复一个序列:

        >>> repetitions=[]
        >>> torep=[1,2,3,4]
        >>> nrep= 2
        >>> for i in range(nrep):
        >>>     repetitions=repetitions+torep
        >>> print(repetitions)
        [1, 2, 3, 4, 1, 2, 3, 4]
        

        【讨论】:

          【解决方案6】:

          numpy.repeat 已被提及,这显然与您想要的相同。但为了完整起见,repeat 也来自itertools 标准库。但是,这通常适用于可迭代对象,因此它不允许按索引重复(因为可迭代对象通常没有定义索引)。

          我们可以使用那里给出的代码作为粗略的等价物

          def repeat(object, times=None):
              # repeat(10, 3) --> 10 10 10
              if times is None:
                  while True:
                      yield object
              else:
                  for i in xrange(times):
                      yield object
          

          定义我们自己的广义重复:

          def repeat_generalised(object, times=None):
              # repeat(10, 3) --> 10 10 10
              if times is None:
                  while True:
                      yield object
              else:
                  for reps, elem in zip(times, object):
                      for i in xrange(reps): 
                          yield elem
          

          问题当然是你必须定义很多可能的边缘情况(如果对象和时间有不同数量的元素会发生什么?),这取决于你的个人用例。

          【讨论】:

            【解决方案7】:

            以下可能对您有用:

            >>>[['a','b'],['A','B']]*5
            
            
            [['a', 'b'], ['A', 'B'], ['a', 'b'], ['A', 'B'], ['a', 'b'], ['A', 'B'], ['a', 'b'], ['A', 'B'], ['a', 'b'], ['A', 'B']]
            

            【讨论】:

              【解决方案8】:

              这是我对Rrep的克隆的尝试:

              def rep(x, times = 1, each = 1, length_out = None):
                  if not isinstance(times, list):
                      times = [times]
              
                  res = ''.join([str(i) * each for i in x])
              
                  if len(times) > 1:   
                      res = ''.join(str(i) * m for i, m in zip(x, times))
                  else:
                      res = ''.join(res * times[0])
                  
                  if length_out is None:
                      return res
                  else:
                      return res[0:length_out]
              

              重现R 示例:

              rep(range(4), times = 2)
              rep(range(4), each = 2)
              rep(range(4), times = [2,2,2,2])
              rep(range(4), each = 2, length_out = 4)
              rep(range(4), each = 2, times = 3)
              

              除了没有回收较短的向量/列表(imo 这是R最差功能)。

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2012-08-05
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2022-08-03
                相关资源
                最近更新 更多