在Python中对一系列数据进行分组

6

标题编辑:修正大写和添加“for python”。

有没有更好或更标准的方法来完成我所描述的操作? 我想要这样的输入:

[1, 1, 1, 0, 2, 2, 0, 2, 2, 0, 0, 3, 3, 0, 1, 1, 1, 1, 1, 2, 2, 2]

被转换成这样:

[0, 1, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 3, 0, 0, 0, 1, 0, 0, 0, 2, 0]

或者,更好的是,像这样(以不同的方式描述类似的输出,但现在不限于整数):

标签:[1, 2, 3, 1, 2]

位置(其中1标识了第一个可占用的位置,根据我的matplotlib图):[2, 7, 12.5, 17, 21]

输入数据是将绘图分类的分类数据 - 在下面的图片中,分组绘图共享一个分类特征,我只想为该组标记一次。 我将使用2个轴来处理两个不同的变量,但我认为现在这不是重点。

注意:此图像不反映任何样本数据集 - 它只是为了传达将类别分组在一起的想法。 由于第一个两个和第二个垂直数据组之间有一个空白区域,因此应在x = 5处标记a组,而0是右侧线。

演示将刻度标记放置在数据类别中心的图像

这就是我拥有的:

data = [1, 1, 1, 2, 2, 2, 2, 2, 3, 4, 3, 2, 2, 1, 1, 1, 1]
last = None
runs = []
labels = []
run = 1
for x in data:
    if x in (last, 0):
        run += 1
    else:
        runs.append(run)
        run = 1
        labels.append(x)
    last = x
runs.append(run)
runs.pop(0)
labels.append(x)
tick_positions = [0]
last_run = 1
for run in runs:
    tick_positions.append(run/2.0+last_run/2.0+tick_positions[-1])
    last_run = run
tick_positions.pop(0)
print tick_positions
1个回答

8
要获取标签,您可以使用itertools groupby
>>> import itertools
>>> numbers = [1, 1, 1, 0, 2, 2, 0, 2, 2, 0, 0, 3, 3, 0, 1, 1, 1, 1, 1, 2, 2, 2]
>>> list(k for k, g in itertools.groupby(numbers))
[1, 0, 2, 0, 2, 0, 3, 0, 1, 2]

要去除零,您可以使用推导式:

>>> list(k for k, g in itertools.groupby(x for x in numbers if x != 0))
[1, 2, 3, 1, 2]

如果您也想获取这些位置,那么您需要像您已经在做的那样自己迭代列表。groupby不会为您跟踪这个。

1
这正是我想象中存在于某个地方的东西 - 这让我想起 '某个地方' 几乎总是 itertools。谢谢。 - Thomas
2
  1. 位置也很重要
  2. 两个2序列之间的那个0也应该被忽略。我想除了生成中间数组,没有其他选择,仅仅分组所有重复值是不够的。
- rsenna
rsenna 是正确的,这并不适用于我需要的所有东西,但我期望它是我能找到的最简单的解决方案 - 看起来对我的问题的精确答案应该是“不”,但那很无聊。 - Thomas

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