Python - 对数组列表进行分类第 2 部分
Posted
技术标签:
【中文标题】Python - 对数组列表进行分类第 2 部分【英文标题】:Python - Categorizing the list of array part 2 【发布时间】:2012-05-25 10:40:18 【问题描述】:我希望有人可以帮助我解决我(再次)遇到的问题。
如果我有坐标:
x = array[0,1,2,3,4,3,2,3,-2,-4,-7,2,2]
y = array[0,1,2,3,4,5,6,7,8,9,10,11,12]
在Categorizing the list of array in python 的帮助下,我可以:
x = [(0, 1, 2, 3, 4), (4, 3, 2), (2, 3), (3, -2, -4, -7), (-7, 2), (2, 2)]
问题是,我应该如何让 y 变成这样:
y = [(0,1,2,3,4),(4,5,6),(6,7),(7,8,9,10),(10,11),(11,12)]
因为 x 和 y 实际上是坐标,并且它们彼此有界。
我尝试过使用循环功能,但发现代码仍然错误
se = []
for i in range(len(z)):
k = z[i]
for i in range(len(k)):
se.append(y[i])
最好的问候,
格伦
【问题讨论】:
你真的应该把这个问题包罗万象。在我阅读了您之前的问题之前,我不知道您在说什么。 @jdi,好的。下次我会更加小心。问候 【参考方案1】:我引用了来自your previous question 的@jamylak 的答案,并显示了轻微的修改。
虽然您可以尝试将生成的 x
的模式与您的 y
匹配,但您也可以修改原始解决方案以将 x 和 y 视为点 (x,y):
from itertools import groupby
x = [0,1,2,3,4,3,2,3,-2,-4,-7,2,2]
y = [0,1,2,3,4,5,6,7,8,9,10,11,12]
def slope(a,b): #Returns 1 for inc, 0 for equal and -1 for dec
return (a > b) - (a < b)
def groups(nums):
#
# Change the call to slope() to assume 2d point tuples as values
#
for k,v in groupby(zip(nums,nums[1:]), lambda (x,y): slope(x[0],y[0])):
yield next(v) + tuple(y for x,y in v)
#
# Pass in a zipped data structure
#
print list(groups(zip(x,y)))
# result
[((0, 0), (1, 1), (2, 2), (3, 3), (4, 4)),
((4, 4), (3, 5), (2, 6)),
((2, 6), (3, 7)),
((3, 7), (-2, 8), (-4, 9), (-7, 10)),
((-7, 10), (2, 11)),
((2, 11), (2, 12))]
虽然我不确定生成的格式是否适合您。
您可以通过以下方式将它们分开:
from operator import itemgetter
result = list(groups(zip(x,y)))
x = [map(itemgetter(0), points) for points in result]
y = [map(itemgetter(1), points) for points in result]
print x
# [[0, 1, 2, 3, 4], [4, 3, 2], [2, 3], [3, -2, -4, -7], [-7, 2], [2, 2]]
print y
# [[0, 1, 2, 3, 4], [4, 5, 6], [6, 7], [7, 8, 9, 10], [10, 11], [11, 12]]
或者按照@jamylak 的建议:
x,y = zip(*[zip(*points) for points in result])
为了说明@jamylak 所说的,关于对groups()
方法的修改如何允许N 维点或数据集:
z = ['foo',1,2,'bar',4,5,6,'foo',8,9,10,'bar',12]
print list(groups(zip(x,y,z)))
# result
[((0, 0, 'foo'), (1, 1, 1), (2, 2, 2), (3, 3, 'bar'), (4, 4, 4)),
((4, 4, 4), (3, 5, 5), (2, 6, 6)),
((2, 6, 6), (3, 7, 'foo')),
((3, 7, 'foo'), (-2, 8, 8), (-4, 9, 9), (-7, 10, 10)),
((-7, 10, 10), (2, 11, 'bar')),
((2, 11, 'bar'), (2, 12, 12))]
您可以看到它可以是任意数据集,并且它总是只对每个数据集的第一个元素进行分组。
【讨论】:
感谢您的回复。确实,结果是不可取的。因为我希望 'x' 和 'y' 是分开的,并且它们的格式与上面相同。 x = [(0, 1, 2, 3, 4), (4, 3, 2), (2, 3), (3, -2, -4, -7), (-7, 2), ( 2, 2)] y = [(0,1,2,3,4),(4,5,6),(6,7),(7,8,9,10),(10,11), (11,12)] 因为稍后,我会将它们输入到我的拉格朗日公式中。但我现在试着把它分开。 +1 我喜欢这个解决方案,因为它使用每两个连续点的0th
元素,它支持任意数量的数组,例如。这也适用于z
点列表。我建议用这个替换你的最后一个班轮:x,y = zip(*[zip(*points) for points in groups(zip(x,y))])
@jamylak:很好的建议!我更新以说明您的观点。【参考方案2】:
以下是你想要的:
x = [(0, 1, 2, 3, 4), (4, 3, 2), (2, 3), (3, -2, -4, -7), (-7, 2), (2, 2)]
y = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
s = map(len, x)
s = [0] + [sum(s[:i])-i for i in range(1, len(s))] + [len(y)]
y = [tuple(y[a:b+1]) for a, b in zip(s, s[1:])]
结果:
>>> y
[(0, 1, 2, 3, 4), (4, 5, 6), (6, 7), (7, 8, 9, 10), (10, 11), (11, 12)]
这基本上构建了y
将被拆分的位置列表。我们使用x
中每个元组的长度来计算这一点,但这有点棘手,因为集合的最后一个元素作为下一个元素包含在下一个集合中。
这是一个可能有助于阐明其工作原理的中间值:
>>> zip(s, s[1:])
[(0, 4), (4, 6), (6, 7), (7, 10), (10, 11), (11, 13)]
我们使用它来构造新的y
,如下所示:
[(0, 4), (4, 6), (6, 7), (7, 10), (10, 11), (11, 13)]
\ | \ \ \_ \
| | \ | \ |
[y[0:4+1], y[4:6+1], y[6:7+1], ...]
【讨论】:
我看到了!这就是它的工作原理!谢啦!也感谢您的解释【参考方案3】:有点难看,但它有效:
se = []
y2 = [y[0]]
i = 1
for xrun in x:
first = True
for xv in xrun:
if first:
first = False
continue
y2.insert( len(y2), y[i] )
i += 1
se.insert( len(se), tuple(y2) )
y2 = [y[i-1]]
【讨论】:
【参考方案4】:这个使用 numpy 怎么样,它同时解决了你的第一个问题。
将 numpy 导入为 np x=(0, 1, 2, 3, 4, 3, 2, 3, -2, -4, -7, 2, 2) y=范围(13) #一阶微分,求斜率 dx = list((np.diff(x)>0)*1) #一阶差分丢失了第一个值,但我们总是想保留它 #只需决定它是低于还是高于第二个值 d0=((x[0]-x[1])>0)*1 #将一阶微分添加到二阶微分(峰值) ddx = [d0,]+list(np.abs(np.diff(dx))) p=0 rx=[] ry=[] 对于 enumerate(ddx) 中的 n,v: 如果 v==1: rx.append(元组(x[p:n+1])) ry.append(元组(y[p:n+1])) p=n 打印接收 打印【讨论】:
以上是关于Python - 对数组列表进行分类第 2 部分的主要内容,如果未能解决你的问题,请参考以下文章