【问题标题】:Clustering rows by group based on column value with conditions根据列值和条件按组对行进行聚类
【发布时间】:2018-06-26 08:57:12
【问题描述】:

几天前我打开了这个帖子:

Clustering rows by group based on column value

我们在其中得到了这个结果:

df <- data.frame(ID = c(1,1,1,1,1,1,1,1,1,1,1, 1, 1,1,1,1,1),
      Obs1 = c(1,1,0,1,0,1,1,0,1,0,0,0,1,1,1,1,1),
      Control = c(0,3,3,1,12,1,1,1,36,13,1,1,2,24,2,2,48),
      ClusterObs1 = c(1, 1, 1, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 5))

与:

df <- df %>% 
group_by(ID) %>% 
mutate_at(vars(Obs1), 
        funs(ClusterObs1= with(rle(.), rep(cumsum(values == 1), lengths))))

现在我必须做一些修改:

如果 'Control' 的值大于 12 并且实际的 'Obs1' 值等于 1 并且之前的 'Obs1' 值,'DesiredResultClusterObs1' 值应该加上 +1

df <- data.frame(ID = c(1,1,1,1,1,1,1,1,1,1,1, 1, 1,1,1,1,1),
      Obs1 = c(1,1,0,1,0,1,1,0,1,0,0,0,1,1,1,1,1),
      Control = c(0,3,3,1,12,1,1,1,36,13,1,1,2,24,2,2,48),
      ClusterObs1 = c(1, 1, 1, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 5),
      DesiredResultClusterObs1 = c(1, 1, 1, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 6, 6, 6, 7))

我考虑过添加 if_else 条件,但没有成功,有什么想法吗?

编辑:对于许多列会如何?

【问题讨论】:

  • 我真的很喜欢你简洁的问题。一个非常聪明的评论:我很晚才知道这一点...理想情况下,当它们是 baseR 函数时,避免使用诸如“df”之类的对象名称-以免弄乱其他人的环境...
  • @Tjebo 将考虑新问题。谢谢
  • @Tjebo 这很有趣,我从来没有意识到df 实际上是一个函数。我很确定这是R SO 中最常见的数据名称。
  • @LAP 我知道 :) 我觉得自己像堂吉诃德 ;)

标签: r cluster-computing lag


【解决方案1】:

这似乎有效:

df %>%
  mutate(DesiredResultClusterOrbs1 = with(rle(Control > 12 & Obs1 == 1 & lag(Obs1) == 1),
                                              rep(cumsum(values == 1), lengths)) + ClusterObs1)

   ID Obs1 Control ClusterObs1 DesiredResultClusterOrbs1
1   1    1       0           1                         1
2   1    1       3           1                         1
3   1    0       3           1                         1
4   1    1       1           2                         2
5   1    0      12           2                         2
6   1    1       1           3                         3
7   1    1       1           3                         3
8   1    0       1           3                         3
9   1    1      36           4                         4
10  1    0      13           4                         4
11  1    0       1           4                         4
12  1    0       1           4                         4
13  1    1       2           5                         5
14  1    1      24           5                         6
15  1    1       2           5                         6
16  1    1       2           5                         6
17  1    1      48           5                         7

基本上,我们使用您之前线程中的rle+rep 机制从您的条件的TRUE/FALSE 结果创建一个累积向量,并将其添加到现有的ClusterObs1


如果要创建多个DesiredResultClusterOrbs,可以使用mapply。也许有一个dplyr 解决方案,但这是基础R

数据:

df <- data.frame(ID = c(1,1,1,1,1,1,1,1,1,1,1, 1, 1,1,1,1,1),
                 Obs1 = c(1,1,0,1,0,1,1,0,1,0,0,0,1,1,1,1,1),
                 Obs2 = rbinom(17, 1, .5),
                 Control = c(0,3,3,1,12,1,1,1,36,13,1,1,2,24,2,2,48),
                 ClusterObs1 = c(1, 1, 1, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 5))

df <- df %>%
  mutate_at(vars(Obs2), 
            funs(ClusterObs2= with(rle(.), rep(cumsum(values == 1), lengths))))

循环:

newcols <- mapply(function(x, y){
  with(rle(df$Control > 12 & x == 1 & lag(x) == 1),
       rep(cumsum(values == 1), lengths)) + y
}, df[2:3], df[5:6])

这会生成一个包含新列的矩阵,然后您可以将其重命名并将 cbind 重命名为您的数据:

colnames(newcols) <- paste0("DesiredResultClusterOrbs", 1:2)

cbind.data.frame(df, newcols)

   ID Obs1 Obs2 Control ClusterObs1 ClusterObs2 DesiredResultClusterOrbs1 DesiredResultClusterOrbs2
1   1    1    1       0           1           1                         1                         1
2   1    1    1       3           1           1                         1                         1
3   1    0    0       3           1           1                         1                         1
4   1    1    0       1           2           1                         2                         1
5   1    0    0      12           2           1                         2                         1
6   1    1    0       1           3           1                         3                         1
7   1    1    1       1           3           2                         3                         2
8   1    0    0       1           3           2                         3                         2
9   1    1    1      36           4           3                         4                         3
10  1    0    1      13           4           3                         4                         4
11  1    0    0       1           4           3                         4                         4
12  1    0    1       1           4           4                         4                         5
13  1    1    1       2           5           4                         5                         5
14  1    1    0      24           5           4                         6                         5
15  1    1    1       2           5           5                         6                         6
16  1    1    1       2           5           5                         6                         6
17  1    1    1      48           5           5                         7                         7

【讨论】:

  • 行得通!有很多 Obs 和 ClusterObs 列会怎么样?
  • 查看我的编辑。但是,它不能同时与 dplyr 一起处理多个变量。
  • 我会看看并回复评论!谢谢
猜你喜欢
  • 1970-01-01
  • 2022-01-23
  • 1970-01-01
  • 2019-02-12
  • 2013-12-05
  • 1970-01-01
  • 2022-11-21
  • 1970-01-01
相关资源
最近更新 更多