【问题标题】:How do I calculate Euclidean distances across NA values in r如何计算 r 中跨 NA 值的欧几里得距离
【发布时间】:2021-08-24 14:22:09
【问题描述】:

我有一个这样的日期框架

individual <- c("1",NA,NA,NA,NA,NA,NA,NA,"1","1")
x <- c(665,NA,NA,NA,NA,NA,NA,NA,663,665)
y <- c(-474.5,NA,NA,NA,NA,NA,NA,NA,-474.5,-472.5)
frame <- rep(1:10)
df <- data.frame(individual,x,y,frame)

我有一个标有“个人”的 ID 列、xy 坐标和帧号。

我需要计算行之间但在 NA 值上的 x,y 坐标的欧几里得距离。

因此,在我给出的示例中 - 我需要计算第 1 行和第 9 行以及第 10 行和第 9 行之间的距离。在实际数据中,当然会有更多的行。

最终我需要做的是对数据进行插值,这样如果欧几里德距离5,则忽略不插值。

这是所需的示例结果数据框:

individual <- c("1","1","1","1","1","1","1","1","1","1")
x <- c(665,NA,NA,NA,NA,NA,NA,NA,663,665)
y <- c(-474.5,NA,NA,NA,NA,NA,NA,NA,-474.5,-472.5)
frame <- rep(1:10)
dist_measure <- c(NA,NA,NA,NA,NA,NA,NA,NA,2,2.828427)
df <- data.frame(individual,x,y,frame,dist_measure)

非常感谢任何有关解决此问题的方法的建议。我的第一个想法是拥有一个计算欧几里得距离并将其放入 for 循环的函数。但是我有点坚持如何在 NA 值上进行处理。我认为以某种方式在 tidyverse 中使用 lag 函数会有所帮助,但又不确定如何将其集成到循环/函数中。

提前谢谢你。

【问题讨论】:

  • 将data.frame命名为data.frame是个坏主意。请改用dfmy_data_frame
  • 公平点,已修复 - 谢谢
  • 如果有更多的人,您如何识别可能属于每个人的NA 值?例如,frame 在个体中是否始终如一地变化?是否总是存在第一个和最后一个观察值,并且介于两者之间的所有内容都可能归因于同一个人?
  • 好点,应该更清楚。在给定的框架内可以有多个人。所以第 1 帧可能有多个个体,因此第 1 帧有 2 行,依此类推。有时每个个体可能只有 1 个观察值,因此只有第一个观察值,没有最后一个观察值。这些也将被忽略,因为中间不会有任何插值(这很好)。
  • @cebola 好的,所以我认为问题仍然存在,您如何识别可能基于距离插值的数据“块”?它会是那个人的第一个和最后一个观察值之间的所有值吗?

标签: r dataframe tidyverse


【解决方案1】:

这应该可以。我已将另一个人添加到假设数据中以显示其工作原理。



individual <- c("1",NA,NA,NA,NA,NA,NA,NA,"1","1", 
                "2",NA,NA,NA,NA,NA,NA,NA,"2","2")
x <- c(665,NA,NA,NA,NA,NA,NA,NA,663,665, 
       .665,NA,NA,NA,NA,NA,NA,NA,.663,.665)
y <- c(-474.5,NA,NA,NA,NA,NA,NA,NA,-474.5,-472.5, 
       -.4745,NA,NA,NA,NA,NA,NA,NA,-.4745,-.4725)
frame <- rep(1:10, 2)
df <- data.frame(individual,x,y,frame)


for(i in 1:2){
  tmp <- df[min(which(df$individual == as.character(i))):
              max(which(df$individual == as.character(i))), ]
  ends <- range(which(is.na(tmp$individual))) + c(-1,1)
  if(nrow(tmp) > 1 & ends[1] > 0 & ends[2] <= nrow(tmp)){
   d <- c(dist(tmp[ends, c("x", "y")]))
   if(d < 5){
     df$individual[min(which(df$individual == as.character(i))):
                     max(which(df$individual == as.character(i)))] <- tmp$individual[ends[1]]
   }
  }
}

df
#    individual       x         y frame
# 1           1 665.000 -474.5000     1
# 2           1      NA        NA     2
# 3           1      NA        NA     3
# 4           1      NA        NA     4
# 5           1      NA        NA     5
# 6           1      NA        NA     6
# 7           1      NA        NA     7
# 8           1      NA        NA     8
# 9           1 663.000 -474.5000     9
# 10          1 665.000 -472.5000    10
# 11          2   0.665   -0.4745     1
# 12          2      NA        NA     2
# 13          2      NA        NA     3
# 14          2      NA        NA     4
# 15          2      NA        NA     5
# 16          2      NA        NA     6
# 17          2      NA        NA     7
# 18          2      NA        NA     8
# 19          2   0.663   -0.4745     9
# 20          2   0.665   -0.4725    10

【讨论】:

  • 谢谢@DaveArmstrong。它适用于个人 2,但是否有理由不适用个人 1?该人的距离也应该相同。
  • 不是的,注意xy的值对于个体2除以1000。个体1的距离是1971.363,个体2的距离是1.971363。所以它做到了据我所知是正确的。
  • 对不起,我的意思是第 9 行和第 1 行之间的距离(对于个人 1)也应该小于 5,因为它在第 19 行和第 11 行中,所以我会还期望在此示例中为两个人插入行(从您的行 if(d
  • 个体 1 具有三对值 1-9、1-10 和 9-10。是不是所有的成对距离都必须小于 5?
  • 不只是在帧号/行的间隙之间,所以这里是 1 和 9。
猜你喜欢
  • 2021-01-31
  • 1970-01-01
  • 2021-02-28
  • 2018-08-26
  • 1970-01-01
  • 2018-01-28
  • 2020-11-29
  • 2018-02-14
  • 1970-01-01
相关资源
最近更新 更多