使用 NA 计算列表元素的最小值
Compute minima across list elements with NA
我得到了一个笨拙的解决方案,但觉得为看似简单的东西编写这么多代码很愚蠢。这对于几十 MB 的列表来说非常快,所以我不需要提高效率。但我仍然需要帮助。
我有一个很大的列表(n 个元素,每个元素都是一个长度为 m 的向量)。我需要获得所有 n 个元素的 m 个最小值(如果这令人困惑,我的意思在代码中很明显)。有 NA,在某些情况下有 0 个完整案例,在大多数情况下有 >=1 个完整案例。我写了一些工作正常的代码,但感觉应该有一种更简单的方法可以到达这里。你能精简这段代码吗?
具体来说,有没有办法避免最小函数的条件,有没有应用系列函数可以让我避免第一个 cbind
?
# make data
rawval<-replicate(10, sample(c(1:10, NA), size = 10, replace =T)
, simplify = F)
# this seems clunky, does this function have a name?
mymin<-function(x)ifelse(all(is.na(x)), NA, min(x, na.rm =T))
# I don't see why I should need two apply family functions here
tomin<-sapply(rawval, cbind) %>% apply(MARGIN = 1, FUN = mymin)
抱歉,我怀疑这是一个重复的问题:(
您可以使用 do.call
和 cbind
数据集,并使用 apply
按行应用 hablar::min_
函数。 hablar::min_
returns NA
如果所有值都是 NA
.
apply(do.call(cbind, rawval), 1, hablar::min_)
不想用的话也可以用自己的函数hablar::min_
。
custom_min <- function(x) if(all(is.na(x))) NA else min(x, na.rm = TRUE)
apply(do.call(cbind, rawval), 1, custom_min)
你要的是mapply
。它将函数应用于多个列表的每个元素。请参阅其帮助页面。
我给你推荐一个函数。我不太确定总和部分,但如果我做对了,你只想找到总和为正的行的最小值。
我将 my_function
与 your_function
进行了基准测试,得到了以下结果:
UPDATE:我还在基准测试中包含了一个 my_updated_function
,我只是使用了 pmin.int
。我现在明白你的意思了,如果所有值都是 NA,则将 NA 保留为“最小值”。我之前以为会有负值。
我包含了您建议的 pmin
解决方案(使用 ifelse)和 @jay.sf 解决方案。
rawval <- replicate(
1000,
sample(c(1:10, NA), size = 1000, replace =T),
simplify = F
)
my_function <- function(values) {
sums <- mapply(sum, values, na.rm=TRUE)
mins <- mapply(min, values, na.rm=TRUE)
mins[sums <= 0] <- NA
return(mins)
}
my_updated_function <- function(values) {
mins <- do.call(pmin.int, c(values, na.rm=TRUE))
# if min is zero, all values are NA. NOTE: this only works like this
# because I'm assuming numbers will always be positive integers
# like the example you provided.
mins[mins == 0] <- NA
return(mins)
}
your_function <- function(values) {
mymin<-function(x)ifelse(sum(x, na.rm=T)>0, min(x, na.rm =T), NA)
# I don't see why I should need two apply family functions here
tomin<- apply(sapply(values, cbind), MARGIN = 1, FUN = mymin)
return(tomin)
}
pmin_function <- function(values) {
sums <- mapply(sum, values, na.rm=TRUE)
mins <- do.call(pmin, c(values, na.rm = TRUE))
mins[sums <= 0] <- NA
return(mins)
}
jay_sf_function <- function(values) {
return(sapply(values, \(x) ifelse(!all(is.na(x)), min(x, na.rm=TRUE), NA)))
}
microbenchmark::microbenchmark(
your_function(rawval),
my_function(rawval),
my_updated_function(rawval),
pmin_function(rawval),
jay_sf_function(rawval)
)
Unit: milliseconds
expr min lq mean median uq max neval
your_function(rawval) 29.0871 32.77735 34.676408 34.37340 35.91040 77.6884 100
my_function(rawval) 4.8762 5.16365 5.376355 5.37335 5.52475 7.3706 100
my_updated_function(rawval) 2.6481 2.72655 2.872085 2.78275 2.92460 4.0724 100
pmin_function(rawval) 5.7140 5.95945 6.268012 6.13110 6.35375 9.4198 100
jay_sf_function(rawval) 4.8583 5.13700 6.839790 5.43480 6.45270 47.6075 100
你在找这个吗?这更多是基于您的描述而不是您的代码。
rawval2
# [[1]]
# [1] 2 5 4 2 1 3
#
# [[2]]
# [1] 5 NA 4 1 5 2
#
# [[3]]
# [1] 1 NA 3 NA 2 1
#
# [[4]]
# [1] NA NA NA 5 NA NA
#
# [[5]]
# [1] NA NA NA NA NA NA
sapply(rawval2, \(x) ifelse(!all(is.na(x)), min(x, na.rm=TRUE), NA))
# [1] 1 1 1 5 NA
数据
rawval2 <- list(c(2L, 5L, 4L, 2L, 1L, 3L), c(5L, NA, 4L, 1L, 5L, 2L), c(1L,
NA, 3L, NA, 2L, 1L), c(NA, NA, NA, 5L, NA, NA), c(NA_integer_,
NA_integer_, NA_integer_, NA_integer_, NA_integer_, NA_integer_
))
我得到了一个笨拙的解决方案,但觉得为看似简单的东西编写这么多代码很愚蠢。这对于几十 MB 的列表来说非常快,所以我不需要提高效率。但我仍然需要帮助。
我有一个很大的列表(n 个元素,每个元素都是一个长度为 m 的向量)。我需要获得所有 n 个元素的 m 个最小值(如果这令人困惑,我的意思在代码中很明显)。有 NA,在某些情况下有 0 个完整案例,在大多数情况下有 >=1 个完整案例。我写了一些工作正常的代码,但感觉应该有一种更简单的方法可以到达这里。你能精简这段代码吗?
具体来说,有没有办法避免最小函数的条件,有没有应用系列函数可以让我避免第一个 cbind
?
# make data
rawval<-replicate(10, sample(c(1:10, NA), size = 10, replace =T)
, simplify = F)
# this seems clunky, does this function have a name?
mymin<-function(x)ifelse(all(is.na(x)), NA, min(x, na.rm =T))
# I don't see why I should need two apply family functions here
tomin<-sapply(rawval, cbind) %>% apply(MARGIN = 1, FUN = mymin)
抱歉,我怀疑这是一个重复的问题:(
您可以使用 do.call
和 cbind
数据集,并使用 apply
按行应用 hablar::min_
函数。 hablar::min_
returns NA
如果所有值都是 NA
.
apply(do.call(cbind, rawval), 1, hablar::min_)
不想用的话也可以用自己的函数hablar::min_
。
custom_min <- function(x) if(all(is.na(x))) NA else min(x, na.rm = TRUE)
apply(do.call(cbind, rawval), 1, custom_min)
你要的是mapply
。它将函数应用于多个列表的每个元素。请参阅其帮助页面。
我给你推荐一个函数。我不太确定总和部分,但如果我做对了,你只想找到总和为正的行的最小值。
我将 my_function
与 your_function
进行了基准测试,得到了以下结果:
UPDATE:我还在基准测试中包含了一个 my_updated_function
,我只是使用了 pmin.int
。我现在明白你的意思了,如果所有值都是 NA,则将 NA 保留为“最小值”。我之前以为会有负值。
我包含了您建议的 pmin
解决方案(使用 ifelse)和 @jay.sf 解决方案。
rawval <- replicate(
1000,
sample(c(1:10, NA), size = 1000, replace =T),
simplify = F
)
my_function <- function(values) {
sums <- mapply(sum, values, na.rm=TRUE)
mins <- mapply(min, values, na.rm=TRUE)
mins[sums <= 0] <- NA
return(mins)
}
my_updated_function <- function(values) {
mins <- do.call(pmin.int, c(values, na.rm=TRUE))
# if min is zero, all values are NA. NOTE: this only works like this
# because I'm assuming numbers will always be positive integers
# like the example you provided.
mins[mins == 0] <- NA
return(mins)
}
your_function <- function(values) {
mymin<-function(x)ifelse(sum(x, na.rm=T)>0, min(x, na.rm =T), NA)
# I don't see why I should need two apply family functions here
tomin<- apply(sapply(values, cbind), MARGIN = 1, FUN = mymin)
return(tomin)
}
pmin_function <- function(values) {
sums <- mapply(sum, values, na.rm=TRUE)
mins <- do.call(pmin, c(values, na.rm = TRUE))
mins[sums <= 0] <- NA
return(mins)
}
jay_sf_function <- function(values) {
return(sapply(values, \(x) ifelse(!all(is.na(x)), min(x, na.rm=TRUE), NA)))
}
microbenchmark::microbenchmark(
your_function(rawval),
my_function(rawval),
my_updated_function(rawval),
pmin_function(rawval),
jay_sf_function(rawval)
)
Unit: milliseconds
expr min lq mean median uq max neval
your_function(rawval) 29.0871 32.77735 34.676408 34.37340 35.91040 77.6884 100
my_function(rawval) 4.8762 5.16365 5.376355 5.37335 5.52475 7.3706 100
my_updated_function(rawval) 2.6481 2.72655 2.872085 2.78275 2.92460 4.0724 100
pmin_function(rawval) 5.7140 5.95945 6.268012 6.13110 6.35375 9.4198 100
jay_sf_function(rawval) 4.8583 5.13700 6.839790 5.43480 6.45270 47.6075 100
你在找这个吗?这更多是基于您的描述而不是您的代码。
rawval2
# [[1]]
# [1] 2 5 4 2 1 3
#
# [[2]]
# [1] 5 NA 4 1 5 2
#
# [[3]]
# [1] 1 NA 3 NA 2 1
#
# [[4]]
# [1] NA NA NA 5 NA NA
#
# [[5]]
# [1] NA NA NA NA NA NA
sapply(rawval2, \(x) ifelse(!all(is.na(x)), min(x, na.rm=TRUE), NA))
# [1] 1 1 1 5 NA
数据
rawval2 <- list(c(2L, 5L, 4L, 2L, 1L, 3L), c(5L, NA, 4L, 1L, 5L, 2L), c(1L,
NA, 3L, NA, 2L, 1L), c(NA, NA, NA, 5L, NA, NA), c(NA_integer_,
NA_integer_, NA_integer_, NA_integer_, NA_integer_, NA_integer_
))