计数并列出R中具有某些值的特定列

ix0qys7i  于 2023-04-03  发布在  其他
关注(0)|答案(2)|浏览(133)

我有一个df,其中有多个感兴趣的列(比如在示例中的第3列到第5列),这些列的值是0或1。行表示单个网格单元格。T使用R,我现在想在这个df中添加一个列'COUNT',它列出每个单元格**有多少个列3到5中有1,然后添加另一个列'NAMES'列出列的名称
这里有一个df的例子

df <- data.frame(var1 = c(sample(c(0:1), 10, replace = T)), 
                  var2 = c(sample(c(0:1), 10, replace = T)), 
                  var3 = c(sample(c(0:1), 10, replace = T)),
                  var4 = c(sample(c(0:1), 10, replace = T)),
                  var5 = c(sample(c(0:1), 10, replace = T)),
                  var6 = c(sample(c(0:1), 10, replace = T)))

不知道这是否重要,有问题的df是类'sf'和'data.frame'。任何想法如何在R中做到这一点将非常感谢。

ljsrvy3e

ljsrvy3e1#

使用tidyverse-通过pick对'var 3'到'var 5'列执行操作来创建COUNT,并获得行求和(rowSums-因为它是二进制的,0值不会相加),然后循环across列,用列名替换1(cur_column()),默认情况下TRUE将是NA,通过粘贴将tibble列转换为具有unnest_widerunite的适当列,同时删除具有na.rm = TRUE的NA,将NAMES_转换为单列

library(dplyr) # version >= 1.1.0
library(tidyr)
library(stringr) 
df %>% 
  mutate(COUNT = rowSums(pick(var3:var5)),
   NAMES = across(var3:var5, ~ case_when(as.logical(.x) ~ cur_column()))) %>% 
  unnest_wider(NAMES, names_sep = "_") %>%
  unite(NAMES, starts_with("NAMES_"), sep = ", ",  na.rm = TRUE)
  • 输出
# A tibble: 10 × 8
    var1  var2  var3  var4  var5  var6 COUNT NAMES             
   <int> <int> <int> <int> <int> <int> <dbl> <chr>             
 1     0     0     1     1     0     0     2 "var3, var4"      
 2     0     0     1     1     1     0     3 "var3, var4, var5"
 3     1     1     1     0     1     1     2 "var3, var5"      
 4     0     1     0     0     0     1     0 ""                
 5     0     0     0     1     0     1     1 "var4"            
 6     0     1     1     0     0     0     1 "var3"            
 7     0     1     0     0     1     1     1 "var5"            
 8     1     1     1     0     1     0     2 "var3, var5"      
 9     0     1     1     1     1     1     3 "var3, var4, var5"
10     0     0     0     1     1     0     2 "var4, var5"
eeq64g8w

eeq64g8w2#

下面是一个基本的R方法:

cols  <- names(df)[3:5] # "var3" "var4" "var5"

df$COUNT  <- rowSums(df[cols])

df$NAMES  <- apply(df[cols], 1, \(x) {
    col_names  <- paste(
       cols[as.logical(x)], collapse = ";"
    )
    if(col_names == "") col_names  <- NA_character_
    col_names
}
)

#    var1 var2 var3 var4 var5 var6 COUNT          NAMES
# 1     1    1    0    1    0    1     1           var4
# 2     0    1    1    0    0    0     1           var3
# 3     1    1    1    1    1    0     3 var3;var4;var5
# 4     1    1    0    1    0    0     1           var4
# 5     0    0    1    1    1    0     3 var3;var4;var5
# 6     0    1    0    1    1    0     2      var4;var5
# 7     1    1    0    1    1    0     2      var4;var5
# 8     1    0    1    1    0    1     2      var3;var4
# 9     1    0    1    0    0    0     1           var3
# 10    0    0    0    0    1    0     1           var5

或者,您可以对data.table使用相同的方法:

setDT(df)

df[, COUNT := rowSums(.SD), .SDcols = cols]

df[, 
    NAMES := apply(.SD, 1, \(x) {
        col_names  <- paste(
        cols[as.logical(x)], collapse = ";"
    )
    if(col_names == "") col_names  <- NA_character_
    col_names
    }
    ), .SDcols = cols
]

# same output

编辑:我注意到输出与@akrun的响应不同,所以我用set.seed(100)重新运行了它,以获得重现性。

相关问题