【问题标题】:How to obtain count information for all variables in a dataframe for each column in in that dataframe in R?如何获取R中该数据框中每一列的数据框中所有变量的计数信息?
【发布时间】:2021-07-01 00:09:24
【问题描述】:

我有一个数据框,其中每一列都是不同的组,并且该列中的每个值都是某种标识符。所有列的长度都不同,并且组之间的值存在一些重叠。我的目标是生成一个新的数据框,其中列名保持不变,初始数据框中存在的每个值都列为行名,并且每个相应单元格中包含的每个值都有计数数据。

输入 DF:

A         B         C         D                                                                                             
Lamp      Car       Orange    Apple   
Potato    Car       Work      Run  
Computer  Sword     Run        
Buns                Tab
Screen
Drain 

我想要获得的 DF,或者类似的东西:

           A         B         C         D                                                                                             
Lamp       1         0         0         0
Potato     1         0         0         0
Computer   1         0         0         0
Buns       1         0         0         0
Screen     1         0         0         0
Drain      1         0         0         0
Car        0         2         0         0
Sword      0         1         0         0
Orange     0         0         1         0
Work       0         0         1         0
Run        0         0         1         1
Tab        0         0         1         0
Apple      0         0         0         1

我曾尝试四处查看类似的帖子,但我一直未能找到非常合适的内容。对此的任何帮助将不胜感激。

【问题讨论】:

  • 如果您将数据放在两列中,一列用于当前列名,另一列用于值,您应该能够使用table 来获取您想要的值。如果需要,您可以使用tidyr::pivot_longer 获取这两列。
  • 你不能有一个 data.frame 列有不同的长度。根据您获取数据的方式,它将失败或用 NA 填充它们。
  • 您能否使用dput 或类似格式以可重现的格式提供您的数据?阅读how to give a reproducible example

标签: r dataframe data-wrangling


【解决方案1】:

这是一个基本的 R 解决方案:

# turn into a list of non-NA characters
dat <- lapply(dat, na.omit)

# get the common levels
lvls <- unique(unlist(dat))

# use table on each of them 
sapply(dat, function(x) table(factor(x, levels = lvls)))
#R>          A B C D
#R> Lamp     1 0 0 0
#R> Potato   1 0 0 0
#R> Computer 1 0 0 0
#R> Buns     1 0 0 0
#R> Screen   1 0 0 0
#R> Drain    1 0 0 0
#R> Car      0 2 0 0
#R> Sword    0 1 0 0
#R> Orange   0 0 1 0
#R> Work     0 0 1 0
#R> Run      0 0 1 1
#R> Tab      0 0 1 0
#R> Apple    0 0 0 1

或者,您可以避免按如下​​方式分配变量:

sapply(dat, function(x, lvls) table(factor(x, lvls)),
       lvls = unique(unlist(dat)))
#R>          A B C D
#R> Lamp     1 0 0 0
#R> Potato   1 0 0 0
#R> Computer 1 0 0 0
#R> Buns     1 0 0 0
#R> Screen   1 0 0 0
#R> Drain    1 0 0 0
#R> Car      0 2 0 0
#R> Sword    0 1 0 0
#R> Orange   0 0 1 0
#R> Work     0 0 1 0
#R> Run      0 0 1 1
#R> Tab      0 0 1 0
#R> Apple    0 0 0 1

或者可能是 R 4.1.0 或更高版本的更高效版本:

dat |> lapply(na.omit) |>
  (\(z) sapply(z, function(x, lvls) table(factor(x, lvls)),
               lvls = unique(unlist(z))))() 
#R>          A B C D
#R> Lamp     1 0 0 0
#R> Potato   1 0 0 0
#R> Computer 1 0 0 0
#R> Buns     1 0 0 0
#R> Screen   1 0 0 0
#R> Drain    1 0 0 0
#R> Car      0 2 0 0
#R> Sword    0 1 0 0
#R> Orange   0 0 1 0
#R> Work     0 0 1 0
#R> Run      0 0 1 1
#R> Tab      0 0 1 0
#R> Apple    0 0 0 1

dat定义如下:

dat <- data.frame(
  A = c("Lamp", "Potato", "Computer", "Buns", "Screen", "Drain"), 
  B = c("Car", "Car", "Sword", NA, NA, NA), 
  C = c("Orange", "Work", "Run", "Tab", NA, NA), 
  D = c("Apple", "Run", NA, NA, NA, NA))

【讨论】:

    【解决方案2】:

    这是一个 tidyverse 方法。首先,重塑为长 df 并聚合组。然后,将变量重新整形为宽 df。

    library(tidyverse)
    
    dat %>% 
      pivot_longer(everything()) %>% 
      drop_na(value) %>% 
      count(name, value) %>% 
      pivot_wider(value, names_from = name, values_from = n, values_fill = 0)
    
    # # A tibble: 13 x 5
    #    value        A     B     C     D
    #    <chr>    <int> <int> <int> <int>
    #  1 Buns         1     0     0     0
    #  2 Computer     1     0     0     0
    #  3 Drain        1     0     0     0
    #  4 Lamp         1     0     0     0
    #  5 Potato       1     0     0     0
    #  6 Screen       1     0     0     0
    #  7 Car          0     2     0     0
    #  8 Sword        0     1     0     0
    #  9 Orange       0     0     1     0
    # 10 Run          0     0     1     1
    # 11 Tab          0     0     1     0
    # 12 Work         0     0     1     0
    # 13 Apple        0     0     0     1
    

    数据集:

    dat <- structure(list(A = c("Lamp", "Potato", "Computer", "Buns", "Screen", 
    "Drain"), B = c("Car", "Car", "Sword", NA, NA, NA), C = c("Orange", 
    "Work", "Run", "Tab", NA, NA), D = c("Apple", "Run", NA, NA, 
    NA, NA)), class = "data.frame", row.names = c(NA, -6L))
    

    【讨论】:

    • 感谢您的评论。这解决了我的问题,非常有帮助!
    【解决方案3】:

    我想我会在base 中试一试。这里可能还有改进的余地...

    dat <- structure(list(
      A = c("Lamp", "Potato", "Computer", "Buns", "Screen", "Drain"),
      B = c("Car", "Car", "Sword", NA, NA, NA),
      C = c("Orange", "Work", "Run", "Tab", NA, NA), 
      D = c("Apple", "Run", NA, NA, NA, NA)),
      class = "data.frame",
      row.names = c(NA, -6L))
    
    # get unique values
    levels = unique(as.vector(as.matrix(dat)))
    
    # coerce dat fields to factor format
    dat <- lapply(dat, factor, levels = levels)
    
    # get frequency of factor levels
    freq <- lapply(dat, table)
    
    # unlist and rotate
    t(do.call(rbind, freq))
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-07-08
      • 1970-01-01
      • 2020-12-27
      • 1970-01-01
      • 1970-01-01
      • 2018-06-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多