不同长度向量之间的计算方法

11

我有5个不同长度的向量。

a <- c(1) #with length of 1
b <- c(4.4,3.5) #length 2
c <- c(5.6,7.8,6.0) #length 3
d <- c(0.8,6.9,8.8,5.8) #length 4
e <- c(1.8,2.5,2.3,6.5,1.1) #length is 5

我试图计算所有向量中元素的平均值:

 #since there are 5 values available for 1st element
 a[1]+b[1]+c[1]+d[1]+e[1] / 5 

 #since there are 4 values available for 2nd element
 b[2]+c[2]+d[2]+e[2] / 4 

#next divide by 3 and 2...1
c[3]+d[3]+e[3] / 3 and so on...

我需要将这些值的平均数存储到另一个数组中,以便能够进一步处理数据。


1
你可以将向量存储在矩阵中(例如在这里 https://dev59.com/Qnvaa4cB1Zd3GeqPEo92),然后使用 rowMeans()na.rm = TRUE - Bas
但是在你的问题中,class(a) 是数字,即 class(c(1)) 是数字。现在你明白为什么给出的解决方案不起作用了吗? - Onyambu
@onyambu 我已经更新了虚假数据。 - Bella_18
使用dput(x)将您的数据包含在内。您的数据无法重现,即运行dput(list(a, b, c, d, e))),复制输出并粘贴到您的问题中。简单地说,接受任何给定解决方案来关闭此问题,同时保持原始问题,并打开一个新问题以处理数据。 - Onyambu
把链接放在这里。 - Onyambu
显示剩余5条评论
8个回答

13

让我们

l <- list(a, b, c, d, e)

然后执行:
tapply(unlist(l), sequence(lengths(l)), mean)
    1     2     3     4     5 
2.720 5.175 5.700 6.150 1.100 

另一种方法:

另一种方法:

rowMeans(sapply(l, `length<-`, max(lengths(l))), na.rm = TRUE)
[1] 2.720 5.175 5.700 6.150 1.100

colMeans(plyr::rbind.fill.matrix(sapply(l, t)), na.rm = TRUE)
    1     2     3     4     5 
2.720 5.175 5.700 6.150 1.100 

10

使用 data.table::transpose 函数:

l <- list(a, b, c, d, e)
sapply(data.table::transpose(l), mean, na.rm = TRUE)
# [1] 2.720 5.175 5.700 6.150 1.100

8

1) 创建向量列表并将每个向量转换为ts对象。 然后使用cbind创建一个多元时间序列对象,其中每个列对应于原始向量中的一个。 然后在该对象上使用rowMeans。

nms <- c("a", "b", "c", "d", "e")
L <- mget(nms)
rowMeans(do.call("cbind", lapply(L, ts)), na.rm = TRUE)
## [1] 2.720 5.175 5.700 6.150 1.100

检查

(a[1] + b[1] + c[1] + d[1] + e[1]) / 5
## [1] 2.72

( b[2]+c[2]+d[2]+e[2]) / 4 
## [1] 5.175

2) 使用上文提到的 L 的另一种方法是使用 sapply:

n <- max(lengths(L))
sapply(1:n, function(i) mean(c(a[i], b[i], c[i], d[i], e[i]), na.rm = TRUE))
## [1] 2.720 5.175 5.700 6.150 1.100

3) 或者按照以下方式使用sapply,其中L和n来自上文:

rowMeans(sapply(L, `[`, 1:n), na.rm = TRUE)

5

另一种方法是将你的向量放入列表中,然后添加NA以使它们长度相等。最后对它们进行rowMeans

mylist <- list(a, b, c, d ,e)
max_L <- max(lengths(mylist))

rowMeans(sapply(mylist, \(x) c(x, rep(NA, max_L - length(x)))), na.rm = T)
[1] 2.720 5.175 5.700 6.150 1.100

3
使用tidyverse
library(dplyr)
library(tidyr)
library(data.table)
mget(letters[1:5]) %>%
  enframe %>%
  unnest(value) %>%
  group_by(grp = rowid(name)) %>% 
  summarise(value = mean(value)) %>%
  pull(value)

-输出

[1] 2.720 5.175 5.700 6.150 1.100

3

看到更大的列表上有广泛的时间范围真是很有趣:

library(plyr)
library(data.table)
library(dplyr)
library(tidyr)
library(tibble)

set.seed(976933858)
l <- unname(split(runif(1e5), sample(1e4, 1e5, TRUE)))

f0 <- function(l) diff(c(0, cumsum(unlist(l)[order(sequence(lengths(l)))])[cumsum(lens <- rev(cumsum(rev(tabulate(lengths(l))))))]))/lens # jblood94
f1 <- function(l) sapply(transpose(l), mean, na.rm = TRUE) # Mael
f2 <- function(l) as.numeric(tapply(unlist(l), sequence(lengths(l)), mean)) # onyambu
f3 <- function(l) rowMeans(sapply(l, `length<-`, max(lengths(l))), na.rm = TRUE) # onyambu
f4 <- function(L) rowMeans(sapply(L, `[`, 1:max(lengths(L))), na.rm = TRUE) # G. Grothendieck
f5 <- function(mylist) {
  # benson23
  max_L <- max(lengths(mylist))
  rowMeans(sapply(mylist, function(x) c(x, rep(NA, max_L - length(x)))), na.rm = T)
}
f6 <- function(l) l %>% enframe %>% unnest(value) %>% group_by(grp = rowid(name)) %>% summarise(value = mean(value)) %>% pull(value) # akrun
f7 <- function(l) unname(colMeans(rbind.fill.matrix(sapply(l, t)), na.rm = TRUE)) # onyambu
f8 <- function(L) rowMeans(do.call("cbind", lapply(L, ts)), na.rm = TRUE) # G. Grothendieck

microbenchmark::microbenchmark(
  jblood94 = f0(l),
  Mael = f1(l),
  onyambu1 = f2(l),
  onyambu2 = f3(l),
  G.Grothendieck1 = f4(l),
  benson23 = f5(l),
  akrun = f6(l),
  onyambu3 = f7(l),
  G.Grothendieck2 = f8(l),
  check = "identical"
)
#> Unit: milliseconds
#>             expr      min        lq       mean    median        uq      max neval
#>         jblood94   1.0303   1.15555   1.544470   1.22690   1.32600   6.4604   100
#>             Mael   1.7522   1.88085   3.214797   1.98215   2.11660  85.0957   100
#>         onyambu1   2.4569   2.61115   4.030907   2.77880   2.94575  99.1389   100
#>         onyambu2   4.1092   4.64760   6.034596   4.91770   6.23725  21.6162   100
#>  G.Grothendieck1   4.7224   5.11220   6.485828   5.63770   7.08075  12.9853   100
#>         benson23  10.7711  12.03325  16.352950  16.06155  19.34285  32.2033   100
#>            akrun  13.8533  16.11800  18.376538  17.09465  20.45810  39.1432   100
#>         onyambu3 342.7180 410.80445 465.461878 451.92355 504.14595 800.1453   100
#>  G.Grothendieck2 465.0375 509.92070 565.463577 553.64825 607.95115 777.0444   100

2
您可以尝试使用以下代码中带有na.rm = TRUE选项的colMeans函数。
L <- max(lengths(lst))
m <- matrix(nrow = L, ncol = L)
m[cbind(rep(seq_along(lst), lengths(lst)), sequence(lengths(lst)))] <- unlist(lst)
colMeans(m, na.rm = TRUE)

它提供了

[1] 2.720 5.175 5.700 6.150 1.100

1

另一个可能的解决方案是基于这样一个想法:通过行绑定 a, b, c, d, e 得到的矩阵是三角形的:

m <- matrix(NA, 5, 5)
m[upper.tri(m, diag = T)] <- c(a, b, c, d, e)
colMeans(t(m), na.rm = T)

#> [1] 2.720 5.175 5.700 6.150 1.100

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接