python - 无监督地将需求聚类为小时组

标签 python cluster-analysis

我有以下数据帧,其中包含每小时相应的产品消耗量。我想根据类似的需求以某种方式对这些时间进行分组 但是 小时的分组必须是连续的,以便有意义。例如,有意义的小时分组可以是 10-12 但不是 (10-12、2、4-5)。

1970-01-01 08:00:00     9
1970-01-01 09:00:00    11
1970-01-01 10:00:00    28
1970-01-01 11:00:00    26
1970-01-01 12:00:00    26
1970-01-01 13:00:00    32
1970-01-01 14:00:00    24
1970-01-01 15:00:00    30
1970-01-01 16:00:00    23
1970-01-01 17:00:00    32
1970-01-01 18:00:00    27
1970-01-01 19:00:00    21
1970-01-01 20:00:00    16
1970-01-01 21:00:00    13
1970-01-01 22:00:00     1
1970-01-01 23:00:00     0

import scipy.cluster.hierarchy as hcluster
temp_data = df.values

ndata = [[td, td] for td in temp_data]
data = np.array(ndata)

# clustering
thresh = (15.0 / 100.0) * (
            max(temp_data) - min(temp_data))  # Threshold 15% of the total range of data

clusters = hcluster.fclusterdata(data, thresh, criterion="distance")

total_clusters = max(clusters)

clustered_index = []
for i in range(total_clusters):
    clustered_index.append([])

for i in range(len(clusters)):
    clustered_index[clusters[i] - 1].append(i)

clustered_range = []
for x in clustered_index:
    clustered_index_x = [temp_data[y] for y in x]
    clustered_range.append((min(clustered_index_x), max(clustered_index_x)))
print(clustered_range)
上面的代码(以及所有无监督的聚类算法)产生了一些聚类值范围,但它不知道小时必须是连续的;它只是对值进行聚类。关于如何解决这个限制并同时强制执行连续的小时组的任何想法?

最佳答案

这是一个非常相似的启发式方法,试图实现您想要的。
本质上,您只需在数组中列出您的需求,并找出最大的连续子数组,其中连续元素的差异绝对值在阈值之内。您可以改变阈值以获得所需的输出。
设置:

import numpy as np, pandas as pd, datetime as dt
date = lambda i: dt.datetime.now()+dt.timedelta(i)
df = pd.DataFrame({"date":[date(i) for i in range(25)], "demand": np.random.randint(0,20,25)})
原始数组:
arr = df.demand.tolist()
[7, 11, 11, 4, 6, 6, 8, 10, 18, 11, 2, 12, 16, 0, 12, 8, 11, 15, 16, 14, 18, 14, 19, 3, 15]
(绝对)差异数组:
diff = [abs(arr[i]-arr[i-1]) for i in range(1,len(arr))]
[4, 0, 7, 2, 0, 2, 2, 8, 7, 9, 10, 4, 16, 12, 4, 3, 4, 1, 2, 4, 4, 5, 16, 12]
将 T 设置为 5。T 是用于窗口的阈值。这是您愿意在连续日期/小时内接受的需求差异的最大值。如果您想增加或减少可接受的差异值,请调整它。
T = 5
当前子数组在每个时间戳小于 T 的间隔长度:
counter = 0
intervals = []
for i in range(len(diff)):
    if diff[i]<T:
        counter += 1
    else:
        counter = 0
    intervals.append(counter)
[1, 2, 0, 1, 2, 3, 4, 0, 0, 0, 0, 1, 0, 0, 1, 2, 3, 4, 5, 6, 7, 0, 0, 0]
满足条件的最大连续区间:
max_interval_idx = max(range(len(intervals)), key=lambda i: intervals[i])
max_interval = intervals[max_interval_idx]
验证答案:
print(arr[max_interval_idx-max_interval +1: max_interval_idx +2])
[12, 8, 11, 15, 16, 14, 18, 14]
请注意,所有连续差异都小于 5。
这是你的答案:
df["date"][max_interval_idx-max_interval +1: max_interval_idx +2]
现在您可以改变 T 以获得不同的分组。

关于python - 无监督地将需求聚类为小时组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65805620/

相关文章:

python 3.7 numpy 加载 ValueError : cannot reshape array of size 5218288 into shape (1974, 3,128,128,3)

python - 在matplotlib图中绘制实心圆并用Qt显示

python - 捕获 CommandOnCooldown 错误

python - 如何将 .txt 文件中的每个单词添加到 Python 列表中?

algorithm - 在像素簇中查找质心

sql - 如何对存储在 SQL 中的附近经纬度位置进行分组

Python - 使用 PIL 绘制不同颜色的簇

r - 如何在 R 中绘制用 kmeans 获得的簇的 3D 图?

python - 在 sklearn 或其他聚类库中进行聚类时,有没有办法强制将一组点分配给同一类?

python - 从命名组解析正则表达式