列表中的空行作为 R 中 data.frame 中的 NA 值

Empty rows in list as NA values in data.frame in R

我有一个数据框如下:

hospital <- c("PROVIDENCE ALASKA MEDICAL CENTER", "ALASKA REGIONAL HOSPITAL", "FAIRBANKS MEMORIAL HOSPITAL", 
          "CRESTWOOD MEDICAL CENTER", "BAPTIST MEDICAL CENTER EAST", "ARKANSAS HEART HOSPITAL", 
          "MEDICAL CENTER NORTH LITTLE ROCK", "CRITTENDEN MEMORIAL HOSPITAL")
state <- c("AK", "AK", "AK", "AL", "AL", "AR", "AR", "AR")
rank <- c(1,2,3,1,2,1,2,3)
df <- data.frame(hospital, state, rank)
df

                                 hospital    state     rank
    1   PROVIDENCE ALASKA MEDICAL CENTER        AK        1
    2   ALASKA REGIONAL HOSPITAL                AK        2
    3   FAIRBANKS MEMORIAL HOSPITAL             AK        3
    4   CRESTWOOD MEDICAL CENTER                AL        1
    5   BAPTIST MEDICAL CENTER EAST             AL        2
    6   ARKANSAS HEART HOSPITAL                 AR        1
    7   MEDICAL CENTER NORTH LITTLE ROCK        AR        2
    8   CRITTENDEN MEMORIAL HOSPITAL            AR        3

我想创建一个函数 rankall,它将排名作为参数,returns 每个州的该排名的医院,如果该州没有匹配的医院,则返回 NA给定等级。例如,我希望 rankall(rank=3) 的输出如下所示:

                           hospital     state 
    AK  FAIRBANKS MEMORIAL HOSPITAL        AK    
    AL                         <NA>        AL
    AR CRITTENDEN MEMORIAL HOSPITAL        AR    

我试过:

rankall <- function(rank) {
split_by_state <- split(df, df$state)
ranked_hospitals <- lapply(split_by_state, function (x) {
    x[(x$rank==rank), ]
})
combined_ranked_hospitals <- do.call(rbind, ranked_hospitals)
return(combined_ranked_hospitals[ ,1:2])
}

但是 rankall(rank=3) returns:

                                 hospital     state     
    AK       FAIRBANKS MEMORIAL HOSPITAL         AK                        
    AR       CRITTENDEN MEMORIAL HOSPITAL        AR             

这省去了我需要跟踪的 NA 值。有没有办法让 R 将函数中列表对象中的空行识别为 NA,而不是空行?除了 lapply 之外,还有其他功能对这项任务更有用吗?

[ 注意:此数据框来自 Coursera R 编程课程。这也是我第一次post上Whosebug,也是我第一次学习编程。感谢所有提供解决方案和建议的人,这个论坛太棒了。 ]

我觉得这个很好用dplyr。唯一奇怪的是当我使用 NA 而不是 "NA" 时总结抱怨。有人知道为什么吗?

library(dplyr)
rankall <- function(chosen_rank){
  group_by(df, state) %>%
    summarize(hospital = ifelse(length(hospital[rank==chosen_rank])!=0,
                                as.character(hospital[rank==chosen_rank]), "NA"),
              rank = chosen_rank)
}

rankall(1)
rankall(2)
rankall(3)

您只需要在您的函数中添加一个 in/else:

rankall <- function(rank) {
    split_by_state <- split(df, df$state)
    ranked_hospitals <- lapply(split_by_state, function (x) {
        indx <- x$rank==rank
        if(any(indx)){
            return(x[indx, ])
        else{
            out = x[1, ]
            out$hospital = NA
            return(out)
        }
    }
}

这是另一种方法:

rankall <- function(rank) {  
  do.call(rbind, lapply(split(df, df$state), function(df) { 
    tmp <- df[df$rank == rank, 1:2]   
    if (!nrow(tmp)) return(transform(df[1, 1:2], hospital = NA)) else return(tmp) 
  })) 
}
rankall(3)
#   hospital state
#   AK  FAIRBANKS MEMORIAL HOSPITAL    AK
#   AL                         <NA>    AL
#   AR CRITTENDEN MEMORIAL HOSPITAL    AR

这是另一种dplyr方法。

fun1 <- function(x) {
            group_by(df, state) %>%
            summarise(hospital = hospital[x],
                      rank = nth(rank, x))
        }

# fun1(3)
#Source: local data frame [3 x 3]
#
#  state                     hospital rank
#1    AK  FAIRBANKS MEMORIAL HOSPITAL    3
#2    AL                           NA   NA
#3    AR CRITTENDEN MEMORIAL HOSPITAL    3