在 R 散点图中插入新矩阵

Insert new matrix in the R scatterplot

我想在我的散点图中插入来自另一个矩阵的新坐标。我正在使用 fviz_cluster 函数为集群生成图表。我想在我的图表中插入称为质心的矩阵坐标,因为它们是安装粪肥堆肥机的每个集群的最佳坐标。我只能为属性生成散点图,如附件所示。代码如下:

> library(readxl)
> df <- read_excel('C:/Users/testbase.xlsx') #matrix containing waste production, latitude and longitude
> dim (df)
[1] 19  3
> d<-dist(df)
> fit.average<-hclust(d,method="average") 
> clusters<-cutree(fit.average, k=6) 
> df$cluster <- clusters # inserting column with determination of clusters
> df
    Latitude    Longitude  Waste   cluster
     <dbl>       <dbl>     <dbl>     <int>
 1    -23.8     -49.6      526.        1
 2    -23.8     -49.6      350.        2
 3    -23.9     -49.6      526.        1
 4    -23.9     -49.6      469.        3
 5    -23.9     -49.6      285.        4
 6    -23.9     -49.6      175.        5
 7    -23.9     -49.6      175.        5
 8    -23.9     -49.6      350.        2
 9    -23.9     -49.6      350.        2
10    -23.9     -49.6      175.        5
11    -23.9     -49.7      350.        2
12    -23.9     -49.7      175.        5
13    -23.9     -49.7      175.        5
14    -23.9     -49.7      364.        2
15    -23.9     -49.7      175.        5
16    -23.9     -49.6      175.        5
17    -23.9     -49.6      350.        2
18    -23.9     -49.6      45.5        6
19    -23.9     -49.6      54.6        6

> ########Generate scatterplot
> library(factoextra)
> fviz_cluster(list(data = df, cluster = clusters))
> 
> 
>  ##Center of mass, best location of each cluster for installation of manure composting machine
> center_mass<-matrix(nrow=6,ncol=2)
> for(i in 1:6){
+ center_mass[i,]<-c(weighted.mean(subset(df,cluster==i)$Latitude,subset(df,cluster==i)$Waste),
+ weighted.mean(subset(df,cluster==i)$Longitude,subset(df,cluster==i)$Waste))}
> center_mass<-cbind(center_mass,matrix(c(1:6),ncol=1)) #including the index of the clusters
> head (center_mass)
          [,1]      [,2] [,3]
[1,] -23.85075 -49.61419    1
[2,] -23.86098 -49.64558    2
[3,] -23.86075 -49.61350    3
[4,] -23.86658 -49.61991    4
[5,] -23.86757 -49.63968    5
[6,] -23.89749 -49.62372    6

新建散点图

考虑经度和纬度的散点图

vars = c("Longitude", "Latitude")

gg <- fviz_cluster(list(df, cluster = dfcluster), choose.var=vars)

gg

由于 fviz_cluster() 函数 returns 一个 ggplot 对象,您应该能够像使用 ggplot().[=25= 一样向绘图添加新点]

这是一个使用模拟数据的示例,我只使用 ggplot2 包中的函数(因为我没有安装 factoextra 包)。

# Dataset with all the points (it's your df data frame)
df <- data.frame(x=1:10, y=1:10)

# Dataset with two "center" points to add to the df points (it's your center_mass matrix)
dc <- data.frame(x=c(2.5, 7.5), y=c(2.5, 7.5))

# ggplot with the initial plot of the df points (it mimics the result from fviz_cluster())
# Note that the plot is not yet shown, it's simply stored in the gg variable
gg <- ggplot() + geom_point(data=df, mapping=aes(x,y))

# Create the plot by adding the center points to the above ggplot as larger red points
gg + geom_point(data=dc, mapping=aes(x,y), color="red", size=3)

产生:

在你的情况下你应该:

  1. 替换行:
    fviz_cluster(list(data = df, cluster = clusters))
    与:
    gg <- fviz_cluster(list(data = df, cluster = clusters))
  2. center_mass 矩阵转换为数据框(通过简单地使用 as.data.frame(center_mass)),然后将其传递给上面示例最后一行中的 geom_point() 调用,并分配适当的您可以在 geom_point()mapping 选项中引用具有 colnames() 功能的列名。

让我知道这是否适合您!

这个答案显示了使用 factoextra 包的 fviz_cluster() 函数的解决方案,而不是我之前的答案中包含的模拟示例。

从 OP 发布的数据框开始,该数据框已经包含 hclust()cutree() 找到的集群:

structure(list(Latitude = c(-23.8, -23.8, -23.9, -23.9, -23.9, 
-23.9, -23.9, -23.9, -23.9, -23.9, -23.9, -23.9, -23.9, -23.9, 
-23.9, -23.9, -23.9, -23.9, -23.9), Longitude = c(-49.6, -49.6, 
-49.6, -49.6, -49.6, -49.6, -49.6, -49.6, -49.6, -49.6, -49.7, 
-49.7, -49.7, -49.7, -49.7, -49.6, -49.6, -49.6, -49.6), Waste = c(526, 
350, 526, 469, 285, 175, 175, 350, 350, 175, 350, 175, 175, 364, 
175, 175, 350, 45.5, 54.6), cluster = c(1L, 2L, 1L, 3L, 4L, 5L, 
5L, 2L, 2L, 5L, 2L, 5L, 5L, 2L, 5L, 5L, 2L, 6L, 6L)), class = "data.frame",
row.names = c(NA, -19L))

我们首先使用 fviz_cluster():

生成集群图
library(factoextra)

# Analysis variables (used when computing the clusters)
vars = c("Latitude", "Longitude", "Waste")

# Initial plot showing the clusters on the first 2 PCs
gg <- fviz_cluster(list(data = df, cluster = df$cluster), choose.vars=vars)
gg

给出:

请注意,此图与 OP 显示的图 不同。原因是 OP 使用的代码使得 df 中存在的 cluster 变量被包含在主成分 的计算中基于。原因是 输入数据框中的所有变量都用于生成绘图 。 (这个结论是通过查看 fviz_cluster() 的源代码并在调试模式下 运行 得出的。)

现在我们计算每个簇的 Waste 加权中心以及每个簇的平均值 Waste(需要在下面将中心添加到图中):
(请注意,代码现在已泛化为 any 找到的簇数)

# Number of clusters found
n_clusters = length( unique(df$cluster) )

# Waste-weighted cluster centers
center_mass <- matrix(nrow=n_clusters, ncol=2, dimnames=list(NULL, c("Latitude", "Longitude")))
for(i in 1:n_clusters) {
  center_mass[i,] <- c(weighted.mean(subset(df,cluster==i)$Latitude,subset(df,cluster==i)$Waste),
                       weighted.mean(subset(df,cluster==i)$Longitude,subset(df,cluster==i)$Waste))
}

# We now compute the average Waste by cluster since,
# in order to add the centers to the fviz_cluster() plot
# we need the information for all three variables used
# in the clustering analysis and generation of the plot
center_mass_with_waste = cbind(center_mass, aggregate(Waste ~ cluster, mean, data=df))
head(center_mass_with_waste)

给出:

   Latitude Longitude cluster    Waste
1 -23.85000 -49.60000       1 526.0000
2 -23.88344 -49.63377       2 352.3333
3 -23.90000 -49.60000       3 469.0000
4 -23.90000 -49.60000       4 285.0000
5 -23.90000 -49.64286       5 175.0000
6 -23.90000 -49.60000       6  50.0500

现在开始最有趣的部分: 将加权中心添加到图中。由于绘图是在主成分轴上完成的,我们需要计算中心的主成分坐标

这是通过运行对完整数据进行主成分分析 (PCA) 并将 PCA 轴旋转应用于中心坐标来实现的。 R的stats包中至少有两个函数可用于运行PCA:prcomp()princomp()。首选方法是 prcomp()(因为它使用奇异值分解来执行特征分析,并使用通常的 N-1 作为方差的除数,而不是 [=30= 使用的 N ]).另外prcomp()fviz_cluster()使用的函数。

因此:

# We first scale the analysis data as we will need the center and scale information
# to properly center and scale the weighted centers for plotting
# Note that proper PCA is always done on centered and scaled data
# in order to accommodate different variable scales and make variables comparable.
# in addition, this is what is done inside fviz_cluster().
X <- scale( df[,vars] )

# We run PCA on the scaled data
summary( pca <- prcomp(X, center=FALSE, scale=FALSE) )

给出:

Importance of components:
                          PC1    PC2    PC3
Standard deviation     1.2263 0.9509 0.7695
Proportion of Variance 0.5012 0.3014 0.1974
Cumulative Proportion  0.5012 0.8026 1.0000

观察前 2 个 PC 的解释方差比例与集群初始图中所示的一致,即:分别为 50.1% 和 30.1%。

我们现在对加权中心进行居中和缩放,使用对完整数据执行的相同中心和缩放操作(绘图需要):

# We center and scale the weighted centers
# (based on the information stored in the attributes of X)
center_mass_with_waste_scaled = scale(center_mass_with_waste[, vars],
                                      center=attr(X, "scaled:center"),
                                      scale=attr(X, "scaled:scale"))

# We compute the PC coordinates for the centers
center_mass_with_waste_pcs = predict(pca, center_mass_with_waste[,vars])

最后,我们将 Waste 加权中心添加到图中(作为红色填充点),并将 Waste 值作为标签。这里我们区分分析变量的数量 (nvars) = 2 或 > 2,因为 fviz_cluster() 仅在 nvars > 2 时执行 PCA,在 nvars = 2 的情况下它只是缩放变量。

# And finally we add the points to the plot (as red filled points)
# distinguishing two cases, because fviz_cluster() does different things
# in each case (i.e. no PCA when nvars = 2, just scaling)
if (length(vars) > 2) {
  # fviz_cluster() performs PCA and plots the first 2 PCs
  # => use PC coordinates for the centers
  gg + geom_point(data=as.data.frame(center_mass_with_waste_pcs),
                  mapping=aes(x=PC1, y=PC2),
                  color="red", size=3) +
       geom_text(data=as.data.frame(pca$x),
                 mapping=aes(x=PC1, y=PC2, label=df$Waste),
                 size=2, hjust=-0.5)
} else {
  # fviz_cluster() does NOT perform PCA; it simply plots the standardized variables
  # => use standardized coordinates for the centers

  # Get the names of the analysis variables as expressions (used in aes() below)
  vars_expr = parse(text=vars)
  gg + geom_point(data=as.data.frame(center_mass_with_waste_scaled),
                  mapping=aes(x=eval(vars_expr[1]), y=eval(vars_expr[2])),
                  color="red", size=3) +
       geom_text(data=as.data.frame(X),
                 mapping=aes(x=eval(vars_expr[1]), y=eval(vars_expr[2]), label=df$Waste),
                 size=2, hjust=-0.5)
}

给出(当 nvars = 3 时):

但是请注意,红点基本上与 fiz_cluster() 计算的原始聚类中心重合,这是因为 LatitudeLongitudeWaste 加权平均值几乎与它们各自的非加权平均值相同(此外,两种计算方法之间唯一略有不同的中心是集群 2 的中心——通过比较每个集群的加权平均值和未加权平均值可以看出(此处未完成))。