【问题标题】:How to get the count of occurence by a given range of a values in a perticular column in a data frame in R?如何通过R中数据框中特定列中给定范围的值获取出现次数?
【发布时间】:2015-12-30 13:50:32
【问题描述】:

我的数据框如下:

ds <- c("ab", "ab", "cd", "ab", NA, "gh")
member1age<-c(9, 21, 39, NA, 69, 90)
member1gender<-c(1,2,1,1,2,NA)
member2age<-c(15,30, 60, 21,12, 45)
member2gender<-c(1,2,2,1,2,1)
member3age<-c(17,2,90,NA,31,5)
member3gender<-c(1,1,2,NA, 1,2)
member4age<-c(NA, NA,23, NA,NA,NA)
member4gender<-c(NA,NA,1,NA,NA,NA)

df <- data.frame(ds,member1age,member1gender,member2age,member2gender,member3age,member3gender,member4age,member4gender)

我想在特定的 ds 中找出给定年龄范围内每种性别有多少人。

例如 ds-“ab”有多少 15-30 岁的男性。 我想要的输出如下所示;表A:

Age Category    Number of Males %   Number of Females   %   Total Number %
Below 5                 1    20.00             0     -          1      14.29 
6-14                    1    20.00             0     -          1      14.29 
15-30                   3    60.00             2     100.00     5      71.43 
31-45                   0    -                 0     -          0      -   
46-60                   0    -                 0     -          0      -   
> 60                    0    -                 0     -          0      -   
Total                   5    100.00            2     100.00     7      100.00 

到目前为止我尝试过的是

为每个成员列应用以下内容;

forage1<-data.frame(ddply(df, .(ds), summarize,
                      All=length(ds),
                      of6Age=sum(Age1<6),
                      of6.15Age=sum(Age1>=6 & Age1<15),
                      of15.31Age=sum(Age1>=15 & Age1<31),
                      of31.46Age=sum(Age1>=31 & Age1<46),
                      of46.60Age=sum(Age1>=46 & Age1<=60),
                      of60Age=sum(Age1>60)))

然后将数据框合并在一起,如下所示; mylist

但这不是我应该得到的。我想要的是上面提到的表 A。请以您的善意支持启发我... 提前谢谢你...!!!

【问题讨论】:

    标签: r subset plyr


    【解决方案1】:

    您应该首先以正确的方式构建数据:

    df <- data.frame(ds = rep(ds,4),
                     age = c(member1age,member2age,member3age, member4age),   
                     gender = c(member1gender,member2gender,member3gender,member4gender))
    

    然后使用cut对你的人口年龄进行分类:

    df$AgeCategory = cut(df$age, 
                         breaks=c(-1,5,14,30,45,60,Inf), 
                         labels=c('Below 5','6-14','15-30','31-45','46-60','>60'),
                         right=T)
    

    最后总结一下——这里我用data.table包:

    library(data.table)
    

    那么数据框df就得转成数据表了

    df = setDT(df)
    

    之后

    dt = setkey(dt, AgeCategory, ds)
    dt = dt[!is.na(ds) & !is.na(AgeCategory)]      #not interested by NA in these columns
    dt = dt[CJ(unique(AgeCategory),unique(ds)), allow.cartesian=T][is.na(gender), gender:=0]
    
    dt[ds=='ab', list(MaleNumber=sum(gender==1), FemaleNumber=sum(gender==2)),AgeCategory][
       ,c('MaleRatio', 'FemaleRatio'):=list(MaleNumber/sum(MaleNumber), 
                                            FemaleNumber/sum(FemaleNumber))][]
    
    #   AgeCategory MaleNumber FemaleNumber MaleRatio FemaleRatio
    #1:     Below 5          1            0       0.2           0
    #2:        6-14          1            0       0.2           0
    #3:       15-30          3            2       0.6           1
    #4:       31-45          0            0       0.0           0
    #5:       46-60          0            0       0.0           0
    #6:         >60          0            0       0.0           0
    

    【讨论】:

    • 非常感谢亲爱的上校先生...代码给了我预期的结果。再次感谢您的即时支持...
    • 如果答案有助于考虑接受它/赞成关闭主题!不用担心,问题不是那么简单!
    • 当然!还有另一个问题……希望你也能支持我。结果以我想要的方式显示在控制台中。但是当我查看(dt)时,结果以不同的方式存储。当我将“dt”数据表写入 excel 文件时,它不会以控制台中显示的确切方式给出它。我怎样才能将值按原样放入数据框中,与控制台窗口中显示的相同。由于数据文件非常多,因此排序和过滤非常耗时。希望您能支持我...谢谢!!!
    • 您可以将结果包装在data.frame(...)
    • na.omit(dt, cols = c("ds", "AgeCategory")) 是另一种删除 NA 的方法。 CJ 也有一个 unique= 参数。我会添加 by= 以明确提供分组的位置..
    【解决方案2】:

    首先将您的df 转换为长格式

    library(tidyr)
    library(dplyr)
    long <- df %>% 
      add_rownames("id") %>% 
      gather(complex, value, -ds, -id) %>% 
      extract(
        complex, 
        c("member", "type"), 
        "([[:alpha:]]+[[:digit:]])([[:alpha:]]+)"
      ) %>%
      spread(type, value)
    

    然后使用cut()将年龄分组

    long %>%
      mutate(
        gender = factor(
          gender, 
          levels = c(1, 2), 
          labels = c("male", "female")
        ), 
        fAge = cut(age, c(0, 5, 14, 30, 45, 60, 100))
      ) %>%
      filter(!is.na(fAge), !is.na(gender)) %>%
      group_by(fAge, gender) %>% 
      summarise(count = n()) %>%
      spread(gender, count, fill = 0)
    

    【讨论】:

      猜你喜欢
      • 2018-05-02
      • 2022-10-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-23
      相关资源
      最近更新 更多