在列表中删除 NA

dropping NA in a list

经过多次尝试和失败,我带来了以下数据:

canada <- c(100, 80, 100, 100, 20)
korea <- c(100, "", 100, "", "")
brazil <- c(100, 90, 100, 30, 30)
fruit <- rbind(canada, korea, brazil)
colnames(fruit) <- c("apple", "orange", "banana", "grape", "kiwi")
fruit

我希望它看起来像这样:

> price("korea")
Thank you, Whosebug, for the delicious apple and banana.

所以我尝试了以下方法:

price <- function(val){
  val <- tolower(val)
  myrow <- fruit[val,]
  nation <- tools::toTitleCase(val)

  name.min <- names(myrow)[which.min(c(myrow))]
  name.max <- sapply(seq_along(myrow), 
                     function(x, n, i) {paste0(n[i])},
                     x=myrow, n=names(na.omit(which(myrow == max(myrow)))))
  name.max[length(name.max)] <- paste0("and ", name.max[na.omit(length(name.max))])
  name.max <- paste(name.max, collapse = ", ")

  cat(paste0("My fruits have a NAsty taste at the end: ", name.max))
} 

打印了以下内容:

> price("korea")
My fruits have a NAsty taste at the end: apple, banana, NA, NA, and NA

我是不是用错了na.omit功能?

我想你可以简单地将向量 myrow 包装在 na.omit 中。

as.vector(na.omit(myrow))

例如

as.vector(na.omit(c(NA, 2,2,3)))
[1] 2 2 3

因此,如果您只想获得 name.min 或 name.max,您可以按以下方式进行操作。

name.min <- names(myrow)[which.min(na.omit(myrow))]
name.max <- names(myrow)[which.max(na.omit(myrow))]

这样,您可以省略 sapply() 调用并按如下方式替换。

price <- function(val){
  val <- tolower(val)
  myrow <- fruit[val,]
  nation <- tools::toTitleCase(val)
  #
  if (min(myrow, na.rm = TRUE) == max(myrow, na.rm = TRUE)) {
    name.max <-  as.vector(na.omit(names(myrow)[myrow == max(myrow, na.rm = TRUE)]))
  } else {
    name.max <- names(myrow)[which.max(na.omit(myrow))]
  }
  cat(paste0("My fruits have a NAsty taste at the end: ", paste(name.max, collapse = ", ")))
} 

结果应该符合预期。

# data
canada <- as.numeric(c(100, 80, 100, 100, 20))
korea <- as.numeric(c(100, "", 100, "", ""))
brazil <- as.numeric(c(100, 90, 100, 30, 30))
fruit <- rbind(canada, korea, brazil)
colnames(fruit) <- c("apple", "orange", "banana", "grape", "kiwi")

# run
price("korea")
My fruits have a NAsty taste at the end: apple, banana

seq_along myrow,并用它来访问 n,但是 n 的元素比 myrow 少,因为你删除了所有那些元素值小于 max(myrow)

如果你改变它,你将只得到那些值等于最大值的那些:

price <- function(val){

  val <- tolower(val)
  myrow <- fruit[val,]
  nation <- tools::toTitleCase(val)

  name.min <- names(myrow)[which.min(c(myrow))]
  name.max <- sapply(seq_along(na.omit(which(myrow == max(myrow)))), 
                     function(x, n, i) {paste0(n[i])},
                     x=myrow, n=names(na.omit(which(myrow == max(myrow)))))
  name.max[length(name.max)] <- paste0("and ", name.max[na.omit(length(name.max))])
  name.max <- paste(name.max, collapse = ", ")

  cat(paste0("My fruits don't have a NAsty taste at the end: ", name.max))
} 

就是说,有点不清楚您希望该函数执行什么操作。我相信有一种更优雅的方法可以做到这一点。例如,为什么你计算name.min却从不使用它?

如果您只想要值等于最大值的列名,这样可读性和效率更高:

name.max <- names(myrow[myrow == max(myrow)])