数据集之间的差异

时间:2011-02-01 13:53:51

标签: python math dataset numpy scipy


我有两个数据集作为列表,例如:

xa = [1, 2, 3, 10, 1383, 0, 12, 9229, 2, 494, 10, 49]    
xb = [1, 1, 4, 12, 1100, 43, 9, 4848, 2, 454, 6, 9]

系列是可能包含数万个数字的市场数据,其长度相同。

我需要在百分比中找到“差异”,这表示“百分比系列之间有多少相似/不相似”。
目前我有一个想法是为每个列表构建图表(xa,xb为 Y ax,范围(1,len(xa))为 X ax)。插入xa,xb的函数,然后计算xa,xb(带积分)的面积和xa和xb之间的差异面积。此后,不相似度为(差异区域)* 100%/(xa面积+ xb面积)。

我想知道这个问题是否有更简单的解决方案。 如果不是 - 我怎样才能计算xa,xb的差异面积?图表是用scipy,numpy,matplotlib构建的。

更新:我正在寻找代表集合之间差异的一个数字。百分之是优选的。

5 个答案:

答案 0 :(得分:5)

如果你想要比较两个1D向量的相似性度量,并且最好返回0到1(或0到100%)之间的值, 余弦相似度 满足那些标准(最后的条件)。 (考虑到问题的背景,我不知道是否合适,但你知道背景,所以你当然可以做出决定。)

import numpy as NP
import numpy.linalg as LA

# generate some data
fnx = lambda : NP.random.randint(0, 10, 10)
s1, s2 = fnx(), fnx()

# a function to calculate cosine similarity
cx = lambda a, b : round(NP.inner(a, b)/(LA.norm(a)*LA.norm(b)), 2)

cx(s1, s2)
# returns 0.85

如果您有许多1D向量,那么一种方法可能是测量每个向量与中值向量的余弦相似性。

在一般情况下,余弦相似度返回介于-1和1之间的值,但在使用它的许多(大多数?)实际情况中,可能的值约束在0和1之间。

其次,余弦相似度的公式是点(a,b)/(范数(a)x范数(b)); NumPy有一个点函数,但是,inner是实现点积的NumPy函数。

答案 1 :(得分:3)

这在很大程度上取决于你所寻求的“相似性”的性质。

我想到了两个措施。

  • 计算sqrt((X[i]-Y[i])^2)abs(X[i]-Y[i])的总和,归一化为X和Y的范围,即从min(X,Y)到max(X,Y)。越接近0,数据集越相似。 sqrt版本对小差异更敏感。
  • 计算correlation,它会给你一个+1的度量,与-1完全相似,为'完全不相似'。请注意,此“相似性”必然意味着您的系列会巧妙地相互关注。请查看维基百科文章中的图片。

答案 2 :(得分:2)

这很大程度上取决于你想要做什么。例如,给出一个给定的例子,你可以想象计算一个但不是两个集合中的元素(两个集合的对称差异的长度) - 如果数字对应于测量,那么显然非常糟糕。

你说时间序列,我们可以假设订单很重要吗?

对于时间序列,计算频谱域中的事物通常是有益的,这是另外需要考虑的事情。只有一个数字的东西不太可能给你提供太多信息

答案 3 :(得分:1)

这是你在寻找什么?

xa = [1, 2, 3, 10, 1383, 0, 12, 9229, 2, 494, 10, 49]    
xb = [1, 1, 4, 12, 1100, 43, 9, 4848, 2, 454, 6, 9]
xc = []

for i in range(0, len(xa)-1):
    xc.append(xa[i] - xb[i])

print xc

输出:

[0, 1, -1, -2, 283, -43, 3, 4381, 0, 40, 4]

编辑:

为什么不采用每个值的百分比差异,然后平均全部:

from statlib import stats

xa = [1, 2, 3, 10, 1383, 0, 12, 9229, 2, 494, 10, 49]    
xb = [1, 1, 4, 12, 1100, 43, 9, 4848, 2, 454, 6, 9]
xc = []


for i in range(0, len(xa)-1):
    xc.append(abs(float(xa[i] - xb[i])/(xa[i] + xb[i])/2))

print stats.mean(xc)*100

如果你没有statlib,你可以得到它here

答案 4 :(得分:0)

from __future__ import division
from itertools import izip, repeat
import math

def weighted_mean(values, weights=None):
    total = 0
    number = 0
    if weights is None:
        weights = repeat(1)
    for weight, value in izip(weights, values):
        total += weight * value
        number += weight
    return number and total / number

xa = [1, 2, 3, 10, 1383, 0, 12, 9229, 2, 494, 10, 49]    
xb = [1, 1, 4, 12, 1100, 43, 9, 4848, 2, 454, 6, 9]


print "Option 1, if you want bigger numbers to have a bigger effect on the score"

weights = (math.sqrt(abs(a) * abs(b)) for a, b in izip(xa, xb))
scores = (abs(a) + abs(b) and abs(a - b) / (abs(a) + abs(b)) for a, b in izip(xa, xb))

final_score = weighted_mean(scores, weights)
print "%.02f%%" % (final_score * 100)


print "Option 2, if you want to have all numbers have the same effect on the score"

scores = (abs(a) + abs(b) and abs(a - b) / (abs(a) + abs(b)) for a, b in izip(xa, xb))

final_score = weighted_mean(scores)
print "%.02f%%" % (final_score * 100)

当然,您也可以使用其他类型的权重,例如(abs(a) + abs(b)) / 2,具体取决于您希望如何解释给定的差异。

第二个无环版:

xan = numpy.array(xa)
xbn = numpy.array(xb)
error_threshold = 0.000001
final_score = numpy.mean((abs(xan - xbn) + error_threshold) / (abs(xan) + abs(xbn) + error_threshold))

或者第一个:

scores = (abs(xan - xbn) + error_threshold) / (abs(xan) + abs(xbn) + error_threshold)
weights = numpy.sqrt(abs(xan) * abs(xbn))
final_score = numpy.sum(scores * weights) / numpy.sum(weights)