【问题标题】:Frequency table when there are multiple columns representing one value (R)多列表示一个值时的频率表 (R)
【发布时间】:2022-01-19 22:53:14
【问题描述】:

我有一个这样的数据集:

ID    color1   color2  color3   shape1       shape2        size
55    red     blue     NA       circle       triangle      small
67    yellow  NA       NA       triangle     NA            medium
83    blue    yellow   NA       circle       NA            large
78    red     yellow   blue     square       circle        large
43    green   NA       NA       square       circle        small
29    yellow  green    NA       circle       triangle      medium

我想创建一个数据框,其中我有每个变量的频率和百分比,但我遇到了麻烦,因为在某些情况下有多个相同变量的列。


Variable      Level        Freq        Percent 
 
color         blue          3           27.27
              red           2           18.18
              yellow        4           36.36
              green         2           18.18
              total         11          100.00

shape         circle        5           50.0       
              triangle      3           30.0
              square        2           20.0
              total         10          100.0

size          small         2           33.3
              medium        2           33.3
              large         2           33.3
              total         6           100.0

我相信我需要将这些变量转换为 long,然后使用 summarise/mutate 来获取频率,但我似乎无法弄清楚。非常感谢任何帮助。

【问题讨论】:

    标签: r


    【解决方案1】:

    您可以使用tidyverse 包将数据转换为长格式,然后汇总所需的统计信息。

    library(tidyverse)
    
    df |> 
      # Transform all columns into a long format
      pivot_longer(cols = -ID,
                   names_pattern = "([A-z]+)",
                   names_to = c("variable")) |>
      # Drop NA entries
      drop_na(value) |>
      # Group by variable
      group_by(variable) |>
      # Count
      count(value) |>
      # Calculate percentage as n / sum of n by variable
      mutate(perc = 100* n / sum(n))
    
    # A tibble: 10 x 4
    # Groups:   variable [3]
    #   variable value        n  perc
    #   <chr>    <chr>    <int> <dbl>
    # 1 color    blue         3  27.3
    # 2 color    green        2  18.2
    # 3 color    red          2  18.2
    # 4 color    yellow       4  36.4
    # 5 shape    circle       5  50  
    # 6 shape    square       2  20  
    # 7 shape    triangle     3  30  
    # 8 size     large        2  33.3
    # 9 size     medium       2  33.3
    #10 size     small        2  33.3
    

    【讨论】:

    • 谢谢!我确信这可行,但我意识到在我的真实数据集中,一些列名有多个单词,这会将它们分成单独的列。你知道防止这种情况的方法吗?
    • 您可以在pivot_longer 的“names_pattern”参数中使用稍微不同的正则表达式。例如,类似:“([Az]+|[Az]+\\s[Az]+)”的列名包含单个单词或 (|) 由空格分隔的两个单词 (\\s) .
    【解决方案2】:

    合并和添加到:

    1. Merge multiple frequency tables together in R

    2. Adding a column of total n for each group in a stacked frequency table

    
    library(dplyr)
    library(tidyr)
    library(janitor)
    
    options(digits = 3)
    
    df %>% 
      pivot_longer(
        -ID,
        names_to = "Variable",
        values_to = "Level"
      ) %>% 
      mutate(Variable = str_extract(Variable, '[A-Za-z]*')) %>% 
      group_by(Variable, Level) %>% 
      count(Level, name = "Freq") %>% 
      na.omit() %>% 
      group_by(Variable) %>% 
      mutate(Percent = Freq/sum(Freq)*100) %>% 
      group_split() %>% 
      adorn_totals() %>% 
      bind_rows() %>% 
      mutate(Level = ifelse(Level == last(Level), last(Variable), Level)) %>% 
      mutate(Variable = ifelse(duplicated(Variable) |
                                 Variable == "Total", NA, Variable))
    
    
     Variable    Level Freq Percent
        color     blue    3    27.3
         <NA>    green    2    18.2
         <NA>      red    2    18.2
         <NA>   yellow    4    36.4
         <NA>    Total   11   100.0
        shape   circle    5    50.0
         <NA>   square    2    20.0
         <NA> triangle    3    30.0
         <NA>    Total   10   100.0
         size    large    2    33.3
         <NA>   medium    2    33.3
         <NA>    small    2    33.3
         <NA>    Total    6   100.0
    

    【讨论】:

    • 谢谢!我确信这可行,但我意识到在我的真实数据集中,一些列名有多个单词,这会将它们分成单独的列。你知道防止这种情况的方法吗?
    【解决方案3】:

    base R

    中尝试 list 中的 matrix
    uniq <- unique( sub( "[0-9]","", colnames(dat[,-1]) ) )
    uniq
    [1] "color" "shape" "size"
    
    sapply( uniq, function(x){ tbl <- table( unlist( dat[,grep( x, colnames(dat) )] ) ); 
      rbind( cbind( Percent=round( tbl/sum(tbl)*100, digits=2 ), Freq=tbl ), 
             cbind( sum(tbl/sum(tbl)*100), sum(tbl) ) ) } )
    $color
             Percent Freq
    blue       27.27    3
    green      18.18    2
    red        18.18    2
    yellow     36.36    4
              100.00   11
    
    $shape
             Percent Freq
    circle        50    5
    square        20    2
    triangle      30    3
                 100   10
    
    $size
             Percent Freq
    large      33.33    2
    medium     33.33    2
    small      33.33    2
              100.00    6
    

    获取data.frame

    data.frame( do.call( rbind, sapply( uniq, function(x){ 
      tbl <- table( unlist( dat[,grep( x, colnames(dat) )] ) ); 
      rbind( cbind( Percent=round( tbl/sum(tbl)*100, digits=2 ), Freq=tbl, var=x ), 
             cbind( sum(tbl/sum(tbl)*100), sum(tbl), var=x ) ) } )
     ) )
             Percent Freq   var
    blue       27.27    3 color
    green      18.18    2 color
    red        18.18    2 color
    yellow     36.36    4 color
    X            100   11 color
    circle        50    5 shape
    square        20    2 shape
    triangle      30    3 shape
    X.1          100   10 shape
    large      33.33    2  size
    medium     33.33    2  size
    small      33.33    2  size
    X.2          100    6  size
    

    数据

    dat <- structure(list(ID = c(55L, 67L, 83L, 78L, 43L, 29L), color1 = c("red", 
    "yellow", "blue", "red", "green", "yellow"), color2 = c("blue", 
    NA, "yellow", "yellow", NA, "green"), color3 = c(NA, NA, NA, 
    "blue", NA, NA), shape1 = c("circle", "triangle", "circle", "square", 
    "square", "circle"), shape2 = c("triangle", NA, NA, "circle", 
    "circle", "triangle"), size = c("small", "medium", "large", "large", 
    "small", "medium")), class = "data.frame", row.names = c(NA, 
    -6L))
    

    【讨论】:

    • 谢谢!您知道如何将其从列表转换为数据框或表格吗? as.data.frame() 不工作
    • @alex 查看编辑。还包括总数。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-13
    • 2018-09-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多