如何在R中的2个列表之间进行计算

时间:2018-01-19 04:39:10

标签: r list

我有以下列表Y和列表Z:

例如:

列出Y:

[[1]]
[[1]]$`1`
   V1 V2
 1  1  1
 2  1  2
 3  2  1
 4  2  2

[[1]]$`2`
   V1 V2
9   5  5
10  5  6

[[1]]$`3`
   V1 V2
 5 10  1
 6 10  2
 7 11  1
 8 11  2


[[2]]
[[2]]$`1`
   V1 V2
1   1  1
2   1  2
3   2  1
4   2  2
9   5  5
10  5  6

[[2]]$`2`
   V1 V2
 5 10  1
 7 11  1
 8 11  2

[[2]]$`3`
   V1 V2
 6 10  2

列出Z:

 [[1]]
 [[1]]$`1`
 [1] 2 1

 [[1]]$`2`
 [1] 5 5

 [[1]]$`3`
 [1] 10  1


 [[2]]
 [[2]]$`1`
 [1] 1 1

 [[2]]$`2`
 [1] 11  1

 [[2]]$`3`
 [1] 10  2

我想在列表Y和列表Z之间进行计算:

      (|y-z|+|y-z|)^2

这样ListY [[1]] $ 1中的所有元素减去ListZ [[1]] $ 1下, ListY [[1]] $ 2中的所有元素减去ListZ [[1]] $ 2下一步, ListY [[1]] $ 3中的所有元素减去ListZ [[1]] $ 3

同样适用于ListY [[2]]和List Z [[2]]

 Expected output for (|y-z| + |y-z|)^2 between ListY[[1]] and ListZ[[1]]:
  > 
    $`1`
    1  2  3  4   
    1  2  0  1 

    $`2`
    9 10 
    0  1 

    $`3`
    5 6 7 8
    0 1 1 2




     Expected output for (|y-z| + |y-z|)^2 between ListY[[2]] and ListZ[[2]]:
    > 
    $`1`
    1  2  3  4  5 9 10 
    1  0  0  1

    $`2`
    5 7 8 
    1 0 1

    $`3`
    6  
    0 

例如,这就是我获得预期结果的方式:

   Y[[1]]
    [[1]]$`1`
       V1 V2
     1  1  1
     2  1  2
     3  2  1
     4  2  2

    [[1]]
    [[1]]$`1`
    [1] 2 1

   (|1-2|+|1-1|)^2 = 1
   (|1-2|+|2-1|)^2 = 4
   (|2-2|+|1-1|)^2 = 0
   (|2-2|+|2-1|)^2 = 1



   $`1`
    1  2  3  4  5 9 10 
    1  4  0  1

我怎样才能在R?

中这样做

2 个答案:

答案 0 :(得分:2)

我认为这应该可以解决您的问题。不确定你给出了正确的预期输出,因为我得到了不同的输出。

<强>解释: 最外面的mapply将通过YZu,v将被分配Y[[1],Z[[1]],然后在第二次迭代中分配Y[[2],Z[[2]]

内部mapply将从$1$2获取$3uv的相应值。因此 a 将获得data.frame,而 b 将被分配vector。然后,您可以使用apply逐行迭代,并以矢量化方式进行计算。

试试这个:

mapply(function(u,v){
    result=mapply(function(a,b){
               apply(X = a,MARGIN = 1,
                function(c,d){
                    sum(abs(c-d))^2},b)
                },u,v,SIMPLIFY = TRUE)
            return(result)
            },
        Y,Z,SIMPLIFY = FALSE)


[[1]]
[[1]]$`1`
[1] 1 4 0 1

[[1]]$`2`
[1] 0 1

[[1]]$`3`
[1] 0 1 1 4


[[2]]
[[2]]$`1`
[1]  0  1  1  4 64 81

[[2]]$`2`
[1] 1 0 1

[[2]]$`3`
[1] 0

答案 1 :(得分:2)

我决定以不同的方式做这项工作,作为大脑的早晨锻炼。

# let's first partially flatten the lists:
y2 <- lapply(unlist(y, recursive=FALSE),  as.matrix)
z2 <- unlist(z, recursive=FALSE)
# and the *flat* answer, using sweep and rowSums:
mapply(function(a,b) rowSums(abs(sweep(a,2,b)))^2, y2, z2)

这里有一个缺陷:新数据结构与旧数据结构不同。可以用嵌套的mapply来解决它:

mapply(function(ex, why) mapply(function(a,b) rowSums(abs(sweep(a,2,b)))^2, ex, why), y,z, SIMPLIFY=FALSE)

..但是首先将它定义为一个函数然后将其重新映射然后再次进行mapplyit会更好:

doit <- function(a,b) rowSums(abs(sweep(a,2,b)))^2
mapplyit <- function(a,b) mapply(doit, a,b)
mapply(mapplyit, y,z, SIMPLIFY=FALSE)

......结果是:

[[1]]
[[1]][[1]]
1 2 3 4 
1 4 0 1 

[[1]][[2]]
 9 10 
 0  1 

[[1]][[3]]
5 6 7 8 
0 1 1 4 


[[2]]
[[2]][[1]]
 1  2  3  4  9 10 
 0  1  1  4 64 81 

[[2]][[2]]
5 7 8 
1 0 1 

[[2]][[3]]
6 
0

......以及数据结构(OP应该以可重现的方式提供: - )

y <- list(
  list(
  read.table(text="V1 V2
1  1  1
2  1  2
3  2  1
4  2  2"),
  read.table(text="V1 V2
9   5  5
10  5  6"),
  read.table(text="V1 V2
5 10  1
6 10  2
7 11  1
8 11  2")),
  list(
  read.table(text="V1 V2
1   1  1
2   1  2
3   2  1
4   2  2
9   5  5
10  5  6"),
  read.table(text="V1 V2
5 10  1
7 11  1
8 11  2"),
  read.table(text="V1 V2
6 10  2")))

z <- list(
  list( 
    c(2, 1),
    c(5,5),
    c(10,1)),
  list(
    c(1,1),
    c(11,1),
    c(10,2)
  ))