跨多个子列表的循环计算

问题描述 投票:0回答:1

我有一组老鼠在竞技场中移动的坐标数据,每个试验都有自己的数据框。对于每个文件,我想计算鼠标在给定时间点(帧)与设定对象(在本例中为气味点)的距离。气味点的位置会随着每次试验而变化。由于管道中其他分析的性质,此时我在列表中有我需要的值的数据框。

这里的示例数据显示了我正在使用的列表的结构,使用随机的假数据。

#These data frames mimic the structure of the coordinate data (main variables of interest are frame, x, y)
df1 <- data.frame(frame = seq(1:50), 
                 x = runif(50, min=1, max=90), 
                 y = runif(50, min=1, max=90))
df2 <- data.frame(frame = seq(1:50),
           x = runif(50, min=1, max=90), 
           y = runif(50, min=1, max=90))
#These data frames mimic the structure of the coordinates of the non-moving locations (i.e. odorspot, arena corners. While the only location I'm interested in is the odorspot ("os"), I'm showing this with other coordinate locations because that is how the data is structured after my other processing steps)
med1 <- data.frame(pointname = c("tl", "tr", "bl", "br", "os", "cs"),
                  x = runif(6, min=1, max=90),
                  y = runif(6, min=1, max=90))
med2 <- data.frame(pointname = c("tl", "tr", "bl", "br", "os", "cs"),
                   x = runif(6, min=1, max=90),
                   y = runif(6, min=1, max=90))

datalist <- list(data1 = df1, 
             data2 = df2)
medlist <- list(data1 = med1,
                data2 = med2)
#Example of the list structure
biglist <- list(data = datalist, 
                median.data = medlist)

所以对于每个“数据”数据帧,我想添加一个名为 DistSpot 的新列,即计算鼠标在每一帧处距离气味点的距离。

最终数据应该是这样的:

  frame        x        y SpotDist
1     0 41.18153 84.49540 66.88208
2     1 41.18153 84.51059 66.89718
3     2 41.18153 84.54423 66.93062
4     3 41.03425 84.64317 67.01337
5     4 40.96008 84.93739 67.29827
6     5 40.70080 85.17731 67.51068

biglist$data$data1对应的气味点坐标在biglist$median.data$data1[5,2]中(第五行第二列)

我尝试编写一个循环函数来进行计算,但它没有运行(在闭包类型上给出错误)。我也不确定我是否正确调用了 median.data 变量。

DistanceOdor <- function(x){
  for (i in 1:length(x$data)){
    x$data[i]$diffx <- (x$data[i]$x - x$median.data[5,2])^2 
    x$data[i]$diffy <- (x$data[i]$y - x$median.data[5,3])^2
    x$data[i]$distspot <- sqrt(x$data[i]$diffx + x$data[i]$diffy)
  }
  return(x)
}

提前致谢!

r list loops data-manipulation
1个回答
1
投票

使用基数 R,您可以

Map
处理不同的输入,然后使用
transform
计算欧氏距离。例如

Map(function(pos, ref) { 
  os <- subset(ref, pointname=="os")
  transform(pos, SpotDist = sqrt((x-os$x)^2 + (y-os$y)^2))
}, biglist$data, biglist$median.data)
# $data1
#    frame         x         y  SpotDist
# 1      1 54.588150 60.336306 50.926487
# 2      2 18.358910 64.556675 31.570075
# 3      3 87.014827 69.396838 83.830691
# 4      4 58.930592 84.829107 69.916124
# ...
# $data2
#    frame         x         y SpotDist
# 1      1 68.006640 27.077371 77.26383
# 2      2 76.747999 68.794598 75.35945
# 3      3 76.288808 58.011732 75.31435
# 4      4  9.879642 81.893493 17.74808
# ...

如果我在您提供的代码之前运行

set.seed(15)
,这些是我得到的值。

如果你想使用你的功能,你需要更加小心

[]
vs
[[]]
。使用前者对列表进行子集化,使用后者从列表中提取项目。你可以做

DistanceOdor <- function(x){
  for (i in 1:length(x$data)){
    x$data[[i]]$diffx <- (x$data[[i]]$x - x$median.data[[i]][5,2])^2 
    x$data[[i]]$diffy <- (x$data[[i]]$y - x$median.data[[i]][5,3])^2
    x$data[[i]]$distspot <- sqrt(x$data[[i]]$diffx + x$data[[i]]$diffy)
  }
  return(x)
}
© www.soinside.com 2019 - 2024. All rights reserved.