问题描述
我正在寻找有关如何在我的 df 中添加包含集群 ID 的列的一些帮助(用于集群数据集的算法是 DBSCAN,我尝试了以下操作
# Compute DBSCAN
db = DBSCAN(eps=1,min_samples=30,algorithm='kd_tree',n_jobs=-1).fit(X)
core_samples_mask = np.zeros_like(db.labels_,dtype=bool)
core_samples_mask[db.core_sample_indices_] = True
labels = db.labels_
np.sum(labels)
# Number of clusters in labels,ignoring noise if present.
n_clusters_ = len(set(labels)) - (1 if -1 in labels else 0)
n_clusters_
n_noise_ = list(labels).count(-1)
print('Estimated number of clusters: %d' % n_clusters_)
print('Estimated number of noise points: %d' % n_noise_)
print("Silhouette Coefficient: %0.3f"
% metrics.silhouette_score(X,labels))
df = df.join(pd.DataFrame(labels))
df = df.rename(columns={0:'Cluster'})
df.head
但我有一个似乎不合逻辑的问题。在聚类之前,我的数据集没有缺失值,而当我添加列(集群)时,clsuter=-1 用于噪声等,我也得到缺失值( !),所以当我尝试清理我的数据集时,我没有任何选择,除了排除 cluster=-1 和缺失值,我不想要的东西。你能帮我解决我的问题吗?
您可以在附件中找到包含问题的输出。 聚类列中大约有 3000 个缺失值,我不明白这是怎么发生的。
输入额外列之前数据集的列有 38037 行。
任何评论都会有所帮助。
谢谢
解决方法
您的 df
中的索引发生了一些问题。正如您在 Pandas join
docs 中读到的,如果参数 on
没有被指定:
调用者中的列或索引级别名称以加入其他中的索引,否则加入 index-on-index。
所以,这样的事情正在发生:
labels
Out[66]: array([ 0,1,-1],dtype=int64)
# make dataframe that exactly matches labels
df = pd.DataFrame(labels,columns=['a'])
df
Out[68]:
a
0 0
1 0
2 0
3 1
4 1
5 -1
# change indices
df = df.set_index([pd.Index([0,3,5,7,8])])
df
Out[70]:
a
0 0
1 0
3 0
5 1
7 1
8 -1
df.join(pd.DataFrame(labels))
Out[71]:
a 0
0 0 0.0
1 0 0.0
3 0 1.0
5 1 -1.0
7 1 NaN
8 -1 NaN
如果您不需要当前索引,我建议您在 DBSCAN 之前重置索引:df.reset_index(drop=True,inplace=True)
。
代码中的这一行导致缺失值:
df = df.join(pd.DataFrame(labels))
说明:
pandas.DataFrame.join()
通过索引连接 DataFrame 对象。 “df”DataFrame 有一个 Int64Index,其值范围从 0 到 41187,但只有 38037 个条目 - 这意味着索引值不连续但包含间隙,可能是在创建数据帧之后和代码片段之前删除/过滤行执行。
包含您使用 pd.DataFrame(labels)
创建的标签的 DataFrame 将有自己的索引,值范围从 0 到 38037。如果此 DataFrame 与原始 DataFrame 连接,则生成的 DataFrame 将仅包含索引所在的行原始 DataFrame 的值和标签 DataFrame 匹配,并且由于原始 DataFrame 索引中的间隙,这仅适用于 35246 行。
最简单的解决方案是重新索引原始数据帧,使其再次包含连续的索引值:
df = df.reset_index(drop=True).join(pd.DataFrame(labels))