【问题标题】:Counting all unique strings in a data frame containing strings and numeric values计算包含字符串和数值的数据框中的所有唯一字符串
【发布时间】:2020-12-13 23:59:52
【问题描述】:

我有许多大型数据框,其中偶尔包含字符串值,我想知道唯一的字符串值是什么(忽略数值),如果可能的话,计算这些字符串。

df <- data.frame(1:16)
df$A <- c("Name",0,0,0,0,0,12,12,0,14,NA_real_,14,NA_real_,NA_real_,16,16)
df$B <- c(10,0,"test",0,12,12,12,12,0,14,NA_real_,14,16,16,16,16)
df$C <- c(10,12,14,16,10,12,14,16,10,12,14,16,10,12,14,16)

   X1.16    A    B  C
1      1 Name   10 10
2      2    0    0 12
3      3    0 test 14
4      4    0    0 16
5      5    0   12 10
6      6    0   12 12
7      7   12   12 14
8      8   12   12 16
9      9    0    0 10
10    10   14   14 12
11    11 <NA> <NA> 14
12    12   14   14 16
13    13 <NA>   16 10
14    14 <NA>   16 12
15    15   16   16 14
16    16   16   16 16

我知道我可以在 dplyr 中使用 count 函数,但我有太多唯一数值,所以这不是一个很好的解决方案。在下面的代码中,我能够过滤我的数据,以便只保留包含字母字符的行(尽管这也不是解决方案)。

df %>% filter_all(any_vars(str_detect(., pattern = "[:alpha:]")))

  X1.16    A    B  C
1     1 Name   10 10
2     3    0 test 14

我想要的输出是这样的:

Variable    n 
"Name"      1 
"test"      1 

【问题讨论】:

    标签: r dplyr


    【解决方案1】:

    您可以使用grep 获取字符串值并使用table 对其进行计数:

    stack(table(grep('[[:alpha:]]', unlist(df), value = TRUE)))[2:1]
    

    如果您想要tidyverse 答案,您可以获取长格式数据,只保留其中包含字符的行和count 它们。

    library(dplyr)
    
    df %>%
      mutate(across(.fns = as.character)) %>%
      tidyr::pivot_longer(cols = everything()) %>%
      filter(grepl('[[:alpha:]]', value)) %>%
      count(value)
    
    #  value     n
    #  <chr> <int>
    #1 Name      1
    #2 test      1
    

    【讨论】:

      【解决方案2】:

      上面的@Ronak 和@akrun 击败了我,我的解决方案非常相似 - 如果您想在列中进行计数,可以使用扩展名

      # Coerce to tibble for ease of reading
      df <- df %>% 
        as_tibble() %>%
        mutate(across(.fns = as.character))
      
      df %>% 
        pivot_longer(cols = everything()) %>% 
        summarise(Variable = str_subset(value, "[:alpha:]")) %>% 
        count(Variable, sort = TRUE)
      
      # A tibble: 2 x 2
        Variable     n
        <chr>    <int>
      1 Name         1
      2 test         1
      
      # str_subset is a convenient wrapper around filter & str_detect
      

      添加一些额外的单词来测试

      # Test on extra word counts - replace 12 and 14 with words
      df2 <- df
      df2[df2 == 12] <- 'Name'
      df2[df2 == 14] <- 'test'
      df2
      
      df2 %>% 
        pivot_longer(cols = everything()) %>% 
        summarise(Variable = str_subset(value, "[:alpha:]")) %>% 
        count(Variable, sort = TRUE)
      
      # A tibble: 2 x 2
        Variable     n
        <chr>    <int>
      1 Name        12
      2 test        10
      

      如果你想按列计数

      df2 %>% 
        select(-1) %>% 
        pivot_longer(everything(), names_to = 'col') %>% 
        group_by(col) %>% 
        summarise(Variable = str_subset(value, "[:alpha:]")) %>% 
        count(col, Variable)
      
      # A tibble: 6 x 3
      # Groups:   col [3]
        col   Variable     n
        <chr> <chr>    <int>
      1 A     Name         3
      2 A     test         2
      3 B     Name         4
      4 B     test         3
      5 C     Name         4
      6 C     test         4
      

      【讨论】:

        【解决方案3】:

        我们可以使用filteracross

        library(dplyr)
        library(tidyr)
        library(stringr)
        library(purrr)
        df %>%
           select(-1) %>%
           mutate(across(everything(), as.character)) %>% 
           filter(across(everything(), ~ str_detect(., '[:alpha:]')) %>% reduce(`|`)) %>%
           pivot_longer(everything()) %>% 
           filter(str_detect(value, '[:alpha:]')) %>%
           count(value)
        # A tibble: 2 x 2
        #  value     n
        #  <chr> <int>
        #1 Name      1
        #2 test      1
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-12-11
          • 2020-05-26
          • 2014-07-08
          • 1970-01-01
          相关资源
          最近更新 更多