纠结集群/ kmeans中心回到原始数据框
问题描述:
这是一些数据。纠结集群/ kmeans中心回到原始数据框
df <- data.frame(groupvar=rep(c('a','b'),100),v1=rnorm(200),v2=rnorm(200))
现在我做的每一组中的k表示:
require(dplyr)
kobjs = df %>% group_by(groupvar) %>%
do(kclust = kmeans(cbind(.$v1,.$v2),centers=5))
“kobjs” 看起来是这样的:
groupvar kclust
(fctr) (chr)
1 a <S3:kmeans>
2 b <S3:kmeans>
我想抓住集群分配(并且最好,中心点)并将它们追加到原始数据框中。我想你可以使用扫帚来做到这一点:
require(broom)
merged = kobjs %>%
group_by(groupvar) %>% do(augment(.$kclust[[1]],df))
但不知何故产生了400X4矩阵,而不是一个200X4。那是怎么发生的?我如何得到我想要的行为?
编辑1:解决了我想要的方式,从aosmith的一些见解。有可能是一个方法,使之更加优雅(是left_join必要吗?),但它是我想要的行为:
kobjs = df %>%
do(kmeans(cbind(.$v1,.$v2),centers=5) %>%
fitted(method="centers") %>%
data.frame(cluster=rownames(.),entry=1:length(.),row.names=NULL)) %>%
left_join(df %>% group_by(groupvar) %>% mutate(entry=1:n()),
by=c("entry","groupvar"))
答
在你对整个df
使用augment
,而不是只使用集各组的时刻。这就是为什么你得到的数据集的长度是预期的两倍。
所以你需要使用kobjs
来做类似下面的事情。在制作kobjs
之前,我将种子设置为16。
kobjs %>%
group_by(groupvar) %>%
do(augment(.$kclust[[1]], df[df$groupvar == .$groupvar,]))
Source: local data frame [200 x 5]
Groups: groupvar [2]
.rownames groupvar v1 v2 .cluster
(chr) (fctr) (dbl) (dbl) (fctr)
1 1 a 0.30291472 0.2203811 1
2 3 a -0.51381305 0.1480162 1
3 5 a -0.75246517 -0.6407782 2
4 7 a 0.06453416 1.2965984 3
5 9 a -0.62353541 -1.3240648 2
6 11 a 0.18435121 -1.0513837 5
7 13 a -0.26481666 2.8117979 4
8 15 a 0.56643441 0.1434451 1
9 17 a -0.30406035 -0.1477244 1
10 19 a 1.62538120 -0.5972593 5
.. ... ... ... ... ...
为了得到更像你想要的东西。
您还有其他选择。例如,你可以在原来的do
步骤中使用augment
:
set.seed(16)
df %>% group_by(groupvar) %>%
do(augment(kmeans(cbind(.$v1,.$v2),centers=5), .))
Source: local data frame [200 x 4]
Groups: groupvar [2]
groupvar v1 v2 .cluster
(fctr) (dbl) (dbl) (fctr)
1 a 0.30291472 0.2203811 1
2 a -0.51381305 0.1480162 1
3 a -0.75246517 -0.6407782 2
4 a 0.06453416 1.2965984 3
5 a -0.62353541 -1.3240648 2
6 a 0.18435121 -1.0513837 5
7 a -0.26481666 2.8117979 4
8 a 0.56643441 0.1434451 1
9 a -0.30406035 -0.1477244 1
10 a 1.62538120 -0.5972593 5
.. ... ... ... ...
你也可以从kmeans
物体拉出cluster
这些具有以下do
编码添加到数据集。但是,这并不使用扫帚。
set.seed(16)
df %>% group_by(groupvar) %>%
do(data.frame(., kclust = kmeans(cbind(.$v1,.$v2),centers=5)$cluster))
Source: local data frame [200 x 4]
Groups: groupvar [2]
groupvar v1 v2 kclust
(fctr) (dbl) (dbl) (int)
1 a 0.30291472 0.2203811 1
2 a -0.51381305 0.1480162 1
3 a -0.75246517 -0.6407782 2
4 a 0.06453416 1.2965984 3
5 a -0.62353541 -1.3240648 2
6 a 0.18435121 -1.0513837 5
7 a -0.26481666 2.8117979 4
8 a 0.56643441 0.1434451 1
9 a -0.30406035 -0.1477244 1
10 a 1.62538120 -0.5972593 5
.. ... ... ... ...
编辑添加例如保存从模型两件事情在一个单一的do
通话。
您可以在do
中拟合并命名模型对象,然后从中拉出多个汇总值,但它涉及大括号的使用(我不确定它们是否包含在非理性担心方括号中;-) )。
这里有两种方法,一是建立model
,拉出拟合值作为fit
,并与原始数据集绑定在一起这一切(这是在data.frame
第一.
代表)。
df %>% group_by(groupvar) %>%
do({
model = kmeans(cbind(.$v1, .$v2), centers = 5)
fit = fitted(model, methods = "centers")
data.frame(., fit, cluster = rownames(fit), row.names = NULL)
})
我不总是喜欢做大量的命名,所以第二个选项只是直接作用于model
并跳过fit
一步。
df %>% group_by(groupvar) %>%
do({
model = kmeans(cbind(.$v1, .$v2), centers = 5)
data.frame(., fitted(model, methods = "centers"), cluster = model$cluster, row.names = NULL)
})
谢谢。第一个例子是我正在寻找的行为。我喜欢其他两种方式来做到这一点(我猜想我对方括号非常害怕),但问题是我不知道如何在同样的kmeans调用中同时抓取集群分配和中心。例如: do(data.frame(。,kclust = kmeans(cbind(。$ v1,。$ v2),centers = 5)$ cluster,kcenter = fitted(kmeans(cbind(。$ v1,。$ v2) ,中心= 5)) 是两个kmeans调用,而不是一个任何方式来抓住两个相同的电话? –
没关系,我想我想通了 - 看原文编辑 –
@NicholasRoot我添加了一个编辑以展示如何适应模型的一些选择,并在单个“do”调用中抽出东西(无需多次安装) – aosmith