Python中与R中的"split"函数对应的函数是什么?

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中是否有其他方便的方法?

你能否更清楚地说明你的输入和输出? - Siva Cn
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])

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的split获得的命名列表。

1
很好的解决方案,但我要求一个非iterools.groupby版本;请查看问题。 - dorvak

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]})

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)]

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接