我想对该散点图进行聚类(y 轴是测量的密度,x 轴是时间)。 有什么办法可以得到图中红色突出显示的点吗?在这种情况下使用聚类算法有意义吗?
以下是代码:
df = pd.read_csv(path, sep=';', decimal=",", low_memory=False, skiprows=1).drop(['Session ID'], axis=1)
df = df.iloc[17120:]
print(df.head())
#print(len(df.index))
#df_len = np.arange(len(df.index))
dens = df['Density']
dens = dens.astype(float)
print(dens.dtypes)
start_dens = 78800+6000
dens_sub = dens[start_dens:]
x = np.arange(1,len(dens_sub)+1)
plt.plot(dens_sub)
plt.ylim([1040,1070])
plt.show()
plt.scatter(x, dens_sub)
plt.ylim([1050,1062])
X = x, dens_sub
wccs = []
for i in range(1,11):
kmeans = KMeans(n_clusters=i, max_iter=100)
kmeans.fit(X)
wccs.append(kmeans.inertia_)
我尝试使用合成数据进行聚类,但结果似乎并不好 - 请参阅下面的示例结果和代码。
另一种方法可能是通过从数据生成频谱图将其转换为二维聚类问题。在该时频空间中进行聚类、将非信号聚类归零并对剩余部分应用逆变换可能更可行。
import numpy as np
import matplotlib.pyplot as plt
#
# Synthesise test date
#
noise_time = np.arange(0, 500)
noise = np.random.uniform(low=1050, high=1062, size=len(noise_time))
signal_time = np.arange(0, 500)
signal = 1055 + (
np.sin(2 * np.pi * 0.01 * signal_time) / (0.6 + 1e-3*signal_time)
+ 0.6 * np.sin(2 * np.pi * np.random.rand(len(signal_time)) * signal_time)
)
merged_time = np.arange(0, 500, 0.5)
interp_signal = np.interp(merged_time, signal_time, signal)
interp_signal[::2] = np.nan
interp_noise = np.interp(merged_time, noise_time, noise)
interp_noise[1::2] = np.nan
noised = np.nansum(np.c_[interp_signal[:, None], interp_noise[:, None]], axis=1)
noised = noised.reshape(-1, 1) #sklearn wants a row per sample
#
# Plot the noise, signal, and the noised signal
#
f, axs = plt.subplots(1, 2, figsize=(10, 2), sharey=True, layout='constrained')
axs[0].scatter(merged_time, interp_noise, label='noise')
axs[0].scatter(merged_time, interp_signal, color='red', label='signal')
axs[1].scatter(merged_time, noised, color='maroon', label='noised')
f.legend(ncol=3, loc='upper right')
#
# Preprocess the data
#
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler().fit(noised)
X = scaler.transform(noised)
#
# Try different clustering algorithms & plot
#
from sklearn.cluster import (
KMeans, AgglomerativeClustering,
HDBSCAN, DBSCAN, MeanShift,
AffinityPropagation, SpectralClustering,
OPTICS
)
kmeans = KMeans(n_clusters=3).fit(X)
f, axs = plt.subplots(4, 2, figsize=(10, 10), sharex=True, sharey=True)
for i, clusterer in enumerate([KMeans(n_clusters=3),
AgglomerativeClustering(n_clusters=3),
HDBSCAN(alpha=40, allow_single_cluster=True, min_cluster_size=5),
DBSCAN(eps=0.05, min_samples=30),
MeanShift(bandwidth=0.4, bin_seeding=True),
AffinityPropagation(damping=0.9825),
SpectralClustering(n_clusters=5),
OPTICS(min_samples=0.1)]
):
clusters = clusterer.fit(X).labels_
ax = axs.flatten()[i]
ax.scatter(merged_time, X, c=clusters, cmap='Set1')
ax.set_title(str(type(clusterer)).split('.')[-1][:-2])
for ax in axs.flatten():
ax.axis('off')
f.subplots_adjust(hspace=0.5)