Python相当于R“split”函数

时间:2013-10-25 18:33:33

标签: python r grouping

在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 个答案:

答案 0 :(得分:4)

从您的示例中,看起来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 :(得分: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)]

答案 2 :(得分:0)

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


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

答案 3 :(得分:0)

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