6

在 R 中,您可以根据另一个向量的因子拆分一个向量:

> a <- 1:10
  [1]  1  2  3  4  5  6  7  8  9 10
> b <- rep(1:2,5)
  [1] 1 2 1 2 1 2 1 2 1 2

> split(a,b)

   $`1`
   [1] 1 3 5 7 9
   $`2`
   [1]  2  4  6  8 10

因此,根据另一个列表的值(根据因素的顺序)对列表(根据 python)进行分组。

除了itertools.groupby方法之外,在 python 中有什么方便的东西吗?

4

4 回答 4

6

从您的示例中,看起来 b 中的每个元素都包含将存储节点的 1 索引列表。Python 缺少 R 似乎具有的自动数值变量,因此我们将返回一个列表元组。如果您可以执行零索引列表,并且您只需要两个列表(即,对于您的 R 用例,1 和 2 是唯一的值,在 python 中它们将是 0 和 1)

>>> a = range(1, 11)
>>> b = [0,1] * 5

>>> split(a, b)
([1, 3, 5, 7, 9], [2, 4, 6, 8, 10])

然后你可以使用itertools.compress

def split(x, f):
    return list(itertools.compress(x, f)), list(itertools.compress(x, (not i for i in f)))

如果您需要更一般的输入(多个数字),类似以下内容将返回一个 n 元组:

def split(x, f):
    count = max(f) + 1
    return tuple( list(itertools.compress(x, (el == i for el in f))) for i in xrange(count) )  

>>> split([1,2,3,4,5,6,7,8,9,10], [0,1,1,0,2,3,4,0,1,2])
([1, 4, 8], [2, 3, 9], [5, 10], [6], [7])
于 2013-10-25T18:51:30.550 回答
1

编辑:警告,这是一个groupby解决方案,这不是 OP 所要求的,但它可能对寻找一种不太具体的方式在 Python 中拆分 R 方式的人有用。


这是itertools.

import itertools
# make your sample data
a = range(1,11)
b = zip(*zip(range(len(a)), itertools.cycle((1,2))))[1]

{k: zip(*g)[1] for k, g in itertools.groupby(sorted(zip(b,a)), lambda x: x[0])}
# {1: (1, 3, 5, 7, 9), 2: (2, 4, 6, 8, 10)}

这为您提供了一个字典,类似于您从 R's 获得的命名列表split

于 2013-10-25T18:58:54.907 回答
1

作为一个长期的 R 用户,我想知道如何做同样的事情。这是一个非常方便的矢量制表功能。这就是我想出的:

a = [1,2,3,4,5,6,7,8,9,10]
b = [1,2,1,2,1,2,1,2,1,2]

from collections import defaultdict
def split(x, f):
    res = defaultdict(list)
    for v, k in zip(x, f):
        res[k].append(v)
    return res

>>> split(a, b)
defaultdict(list, {1: [1, 3, 5, 7, 9], 2: [2, 4, 6, 8, 10]})
于 2018-11-06T02:54:20.600 回答
0

你可以试试:

a = [1,2,3,4,5,6,7,8,9,10]
b = [1,2,1,2,1,2,1,2,1,2]

split_1 = [a[k] for k in (i for i,j in enumerate(b) if j == 1)]
split_2 = [a[k] for k in (i for i,j in enumerate(b) if j == 2)]

结果是:

In [22]: split_1
Out[22]: [1, 3, 5, 7, 9]

In [24]: split_2
Out[24]: [2, 4, 6, 8, 10]

为了使这个概括,您可以简单地迭代 b 中的唯一元素:

splits = {}
for index in set(b):
   splits[index] =  [a[k] for k in (i for i,j in enumerate(b) if j == index)]
于 2013-10-25T18:46:33.383 回答