【问题标题】:R: how to remove data within a subset in a loopR:如何在循环中删除子集中的数据
【发布时间】:2017-11-08 23:32:31
【问题描述】:
df <- data.frame(id = c(1, 2, 3, 3, 3, 4), gender = c("Male", "Female", "Both", "Male", "Female", "Female"))
ids <- unique(df$id)

> df
  id gender
1  1   Male
2  2 Female
3  3   Both
4  3   Male
5  3 Female
6  4 Female 

对于每个唯一的id,我想确保如果对应的genders 是BothMaleFemale,那么我需要删除与Both 对应的行。换句话说,我想要的输出是:

> df
  id gender
1  1   Male
2  2 Female
3  3   Male
4  3 Female
5  4 Female 

我试过写一个循环:

  1. df 子集id 并将每个子集存储到名为sub 的列表中

  2. 在每个sub中,检查性别是否包含“Both”、“Male”和“Female`”

  3. 如果是这样,删除性别=“Both”的行

  4. 重新组合data.frame

但是,下面的代码实际上并不能正常工作,而且非常笨拙...我想知道在dplyr 中使用group_by 是否有更简单的方法?

sub <- list()
for(i in 1:length(ids)){
  sub[[i]] <- subset(df, id %in% ids[i])
  if(all(grepl(sub[[i]]$gender, c("Both", "Male", "Female")))){
    sub[[i]] <- sub[[i]][-which(sub[[i]]$gender == "Both"), ]
  }else sub[[i]] = sub[[i]]
}

【问题讨论】:

  • id 的性别是Both,那id 是否总是同时拥有MaleFemale
  • 不,不一定。

标签: r dataframe


【解决方案1】:

通过使用dplyr

df %>% 
    group_by(id) %>% 
    mutate(A = ifelse(length(unique(gender)) >= 3 & gender == 'Both', F, T)) %>% 
    filter(A) %>% 
    select(-A)
# A tibble: 5 x 2
# Groups:   id [4]
     id gender
  <dbl>  <chr>
1     1   Male
2     2 Female
3     3   Male
4     3 Female
5     4 Female

【讨论】:

  • 您需要使用n_distinctlength(unique(...)) 而不是unique,或者您将因子强制转换为整数。
【解决方案2】:

除了tidyverse解决方案,这里使用lapply的解决方案:

result <- lapply(ids,function(x){
    tmp <- df[df$id == x,]
    if(all(c("Both","Male", "Female") %in% tmp$gender)){
        tmp <- tmp[tmp$gender != "Both",]
    }
    return(tmp)
})
do.call("rbind",result)
#   id gender
# 1  1   Male
# 2  2 Female
# 4  3   Male
# 5  3 Female
# 6  4 Female

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-12-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多