Python-基于时态信息(即时、间隔)计算项目之间的相似性
我想根据项目(0,1,2,3..)的时间信息计算它们之间的相似性。时间信息可以是时间瞬间(startdate)、时间间隔(startdate、enddate)或空(NaT);请参见下面的数据帧(df_)示例Python-基于时态信息(即时、间隔)计算项目之间的相似性,python,time,intervals,similarity,pdist,Python,Time,Intervals,Similarity,Pdist,我想根据项目(0,1,2,3..)的时间信息计算它们之间的相似性。时间信息可以是时间瞬间(startdate)、时间间隔(startdate、enddate)或空(NaT);请参见下面的数据帧(df_)示例 {instant,instant}:如果等于sim=1,否则sim=0 {instant,null}或反之亦然,sim=0 {instant,interval}:如果instant在interval内,则sim=1;如果interval包含一个instant,则sim=1 {interva
m, k = df_for.shape
sim = np.zeros((m, m))
data = df_for.values
for i in range(m):
for j in range(m):
if i != j:
st1 = data[i][0]
ed1 = data[i][1]
st2 = data[j][0]
ed2 = data[j][1]
#both items are null values
if pd.isnull(st1) and pd.isnull(ed1) and pd.isnull(st2) and pd.isnull(ed2):
sim[i][j] = 0.
# {instant, instant} => equal, not equal
if pd.notnull(st1) and pd.isnull(ed1) and pd.notnull(st2) and pd.isnull(ed2):
if st1 == st2:
sim[i][j] = 1.
else:
sim[i][j] = 0.
# {instant, null} => sim is 0
if pd.notnull(st1) and pd.isnull(ed1) and pd.isnull(st2) and pd.isnull(ed2):
sim[i][j] = 0.
# {instant, interval} => meets, during
if pd.notnull(st1) and pd.isnull(ed1) and pd.notnull(st2) and pd.notnull(ed2):
if(st2 <= st1 <= ed2):
sim[i][j] = 1. #a time is between two other times
else:
sim[i][j] = 0.
# {interval, instant} => meets, contains
if pd.notnull(st1) and pd.notnull(ed1) and pd.notnull(st2) and pd.isnull(ed2):
if(st1 <= st2 <= ed1):
sim[i][j] = 1. #a time is between two other times
else:
sim[i][j] = 0.
# {interval, interval} => equal, overlaps, not overlaps
if pd.notnull(st1) and pd.notnull(ed1) and pd.notnull(st2) and pd.notnull(ed2):
if (st1 <= st2 <= ed1) or (st2 <= st1 <= ed2):
intersect = min(ed1,ed2)- max(st1,st2) # earliestend-lateststart
union = max(st1,st2,ed1,ed2) - min(ed1,ed2,st1,st2)
overlaps = intersect/union
#print(intersect/np.timedelta64(1, 'D'),union/np.timedelta64(1, 'D'))
if (st1 > st2 and ed1 < ed2) or (st1 < st2 and ed1 > ed2): # contains, during
overlaps = 1.0
sim[i][j]=overlaps
else:
sim[i][j] = 0.
else:
sim[i][j] = 1.
m,k=df_表示形状
sim=np.零((m,m))
数据=df_表示值
对于范围内的i(m):
对于范围内的j(m):
如果我j:
st1=数据[i][0]
ed1=数据[i][1]
st2=数据[j][0]
ed2=数据[j][1]
#这两项都是空值
如果pd.isnull(st1)和pd.isnull(ed1)以及pd.isnull(st2)和pd.isnull(ed2):
sim[i][j]=0。
#{instant,instant}=>相等,不相等
如果pd.notnull(st1)和pd.isnull(ed1)以及pd.notnull(st2)和pd.isnull(ed2):
如果st1==st2:
sim[i][j]=1。
其他:
sim[i][j]=0。
#{instant,null}=>sim为0
如果pd.notnull(st1)和pd.isnull(ed1)以及pd.isnull(st2)和pd.isnull(ed2):
sim[i][j]=0。
#{instant,interval}=>在
如果pd.notnull(st1)和pd.isnull(ed1)以及pd.notnull(st2)和pd.notnull(ed2):
如果(st2没有尝试在这里给出完整的答案。
我将创建一个类来接收开始和结束时间,然后对构造函数执行所有null notnull检查。
稍后,我将重载比较运算符。例如,eqfor==和nefor=
在重载上,您可以尝试返回整数值,而不是True和False。
有了这些,我可能会重写
即时(数据[i][0],数据[i][1])==即时(数据[j][0],数据[j][1])
然后从中导出所需的内容我可以看到几种简化代码的方法
首先,我建议将比较代码移动到一个单独的函数中,该函数将st1
、ed1
、st2
和ed2
作为参数(顺便提一句,为什么st
(开始时间)而ed
(结束日期)?一致的名称可能更好。)您可以将您的结果返回给调用代码,调用代码将负责在结果数组中进行赋值
说到调用代码……它不需要为每对时间范围调用比较函数。结果应该总是对称的(例如,compare(data[i][0]、data[i][1]、data[j][0]、data[j][1])
将返回与compare(data[j][0]、data[j][1]、data[i][0]、data[i][1]相同的结果。
)因此,只需调用其中一个,并将结果分配给sim[i][j]
和sim[j][i]
如果某个测试表达式:返回1;否则:返回0
块,则只返回比较结果:返回某个测试表达式
。Python的bool
类型是int
的子类,因此当您将它们分配到numpy数组中时,它们应该自动转换为数字(如果希望函数始终返回相同的类型,也可以显式强制转换为float
)
如果isnull(st1)或isnull(st2):返回0。
if isnull(ed2):st1,ed1,st2,ed2=st2,ed2,st1,ed1
0.000277
(0.999/(3600+0.001)
)中,但与较大间隔同时开始的一个将具有1.0
的相似性(一个很大的差异)。更连续变化的相似性度量将来自重叠量除以较小间隔的大小(而不是联合的大小)。对于一个区间完全包含另一个区间,此公式不需要特殊情况,因为默认计算将给出一个相似性1.0
(重叠将是较小区间的大小,因此您将其自身除以)def compare_intervals(st1, et1, st2, et2): # note I've renamed the ed's to et
# all nulls
if pd.isnull(st1) or pd.isnull(st2):
return 0.
# {instant, instant} => equal, not equal
if pd.isnull(et1) and pd.isnull(et2):
return float(st1 == st2)
# {instant, interval} => flip params (to be handled in next block)
if pd.isnull(et1):
st1, et1, st2, et2 = st2, et2, st1, et1
# {interval, instant} => meets, contains
if pd.isnull(et2):
return float(st1 <= st2 <= et1)
# {interval, interval} => equal, overlaps, not overlaps
if (st1 <= st2 <= et1) or (st2 <= st1 <= et2):
intersect = min(et1, et2) - max(st1, st2)
min_interval = min(et1 - st1, et2 - st2) # using minimum instead of union
return intersect / min_interval
return 0. # intervals didn't overlap
m, k = df_for.shape
sim = np.zeros((m, m))
data = df_for.values
for i in range(m):
for j in range(i, m): # we only iterate on j values >= i
if i == j:
sim[i,j] = 1.
else:
sim[i,j] = sim[j,i] = compare_intervals(data[i][0], data[i][1],
data[j][0], data[j][1])
def compare_interval(st1、et1、st2、et2):#注意,我已将ed重命名为et
#所有空值
如果pd.isnull(st1)或pd.isnull(st2):