【问题标题】:How to count the number of columns with a single value?如何计算具有单个值的列数?
【发布时间】:2019-11-07 20:26:20
【问题描述】:

我有一个数据集,其中一堆字符列只有一个值,即列本身的名称。每一行都是一个观察,我想计算每一行存在多少这样的列。

例如:

id multi_value_col single_value_col_1 single_value_col_2
1  A               single_value_col_1 
2  D2              single_value_col_1 single_value_col_2
3  Z6                                 single_value_col_2

我想要添加一个列来计算每行有多少个单值列。像这样:

id multi_value_col single_value_col_1 single_value_col_2  count
1  A               single_value_col_1                     1 
2  D2              single_value_col_1 single_value_col_2  2
3  Z6                                 single_value_col_2  1

我最初的想法是使用mutate_ifn_distinct,将字符串替换为TRUE,然后可以在mutate 中使用rowSums:

data %>% 
 mutate_if(~n_distinct(.) == 1, TRUE, .) %>%
 mutate(count = rowSums???)

但是,我无法让 mutate_if 工作,而且我也不确定 rowSums 命令是否存在跨行可用的 sum_if TRUE 操作?

【问题讨论】:

标签: r conditional-statements dplyr


【解决方案1】:

如果我们检查列名,那么

library(tidyverse)
data %>%
    mutate(count = pmap_int(.[-1], ~ {x1 <- c(...)
                 sum(x1 == names(x1))} ))
#  id multi_value_col single_value_col_1 single_value_col_2 count
#1  1               A single_value_col_1                        1
#2  2              D2 single_value_col_1 single_value_col_2     2
#3  3              Z6                    single_value_col_2     1

或在base R

rowSums(data[-1] == names(data)[-1][col(data[-1])])

如果数据集有 NA,只需将其更改为

rowSums(data[-1] == names(data)[-1][col(data[-1])], na.rm = TRUE)

@thelatemail 建议的其他选项包括转置选定的列,并在逻辑矩阵上执行colSums

nms <- names(data)[nm1]
colSums(t(data[nms]) == nms)

Reduce

Reduce(`+`, Map(`==`, data[nms], nms))

如果打算基于非空白进行计数,在base R 中,我们创建一个包含感兴趣列的逻辑矩阵并对其执行rowSums

nm1 <- grep("single_value", names(data))
data$count <-  rowSums(data[nm1] != "")

dplyr

library(dplyr)
data %>% 
    mutate(count = rowSums(.[nm1] != ""))
#  id multi_value_col single_value_col_1 single_value_col_2 count
#1  1               A single_value_col_1                        1
#2  2              D2 single_value_col_1 single_value_col_2     2
#3  3              Z6                    single_value_col_2     1

数据

data <- structure(list(id = 1:3, multi_value_col = c("A", "D2", "Z6"), 
    single_value_col_1 = c("single_value_col_1", "single_value_col_1", 
    ""), single_value_col_2 = c("", "single_value_col_2", "single_value_col_2"
    )), row.names = c(NA, -3L), class = "data.frame")

【讨论】:

  • 您也可以使用 t 旋转数据集并比较 - colSums(t(data[nms]) == nms) - 其中 nms 是列的名称。或者像基本 R 中的 pmap 这样的功能方法 - Reduce(`+`, Map(`==`, data[nms], nms))
【解决方案2】:

根据您的数据或空白单元格中是否有NA,您可以使用以下基本 R 方法之一,我们首先找出只有一个唯一值的列,然后计算非 NA 或非空白单元格在这些相应的列中的每行。

如果你有NA

cols <- which(sapply(df, function(x) length(unique(na.omit(x)))) == 1)
df$count <- rowSums(!is.na(df[cols]))

df
#  id multi_value_col single_value_col_1 single_value_col_2 count
#1  1               A single_value_col_1               <NA>     1
#2  2              D2 single_value_col_1 single_value_col_2     2
#3  3              Z6               <NA> single_value_col_2     1

如果你有空单元格

cols <- which(sapply(df, function(x) length(unique(x[x!=""]))) == 1)
df$count <- rowSums(df[cols] != "")

【讨论】:

  • 我认为空单元格方法可行,但出现错误:Error in x[x != ""] : object of type 'symbol' is not subsettable.
  • @Khashir 你的数据中有一些T/FTRUE/FALSE 值吗?在应用此之前,您可以将所有列转换为字符吗? df[] &lt;- lapply(df, as.character)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-08-13
  • 2018-12-27
  • 1970-01-01
  • 2019-10-06
相关资源
最近更新 更多