查找使用for循环移动的总距离
我试图找出工人移动的总距离,我的查找使用for循环移动的总距离,r,R,我试图找出工人移动的总距离,我的df看起来像 Name x y John 12 34 John 15 31 John 8 38 John 20 14 我尝试使用dist(rbind())函数,但给出的结果不正确。它只是给出了sqrt((第1行)^2+(第2行)^2+(第3行)^2+(第4行)^2)的结果,我认为这是不正确的 所以我试着使用for循环来实现这一点,这样第1行和第2行、第2行和第3行之间的距离就可以分别计算出来,以后再求和。我该怎么
df
看起来像
Name x y
John 12 34
John 15 31
John 8 38
John 20 14
我尝试使用dist(rbind())
函数,但给出的结果不正确。它只是给出了sqrt((第1行)^2+(第2行)^2+(第3行)^2+(第4行)^2)
的结果,我认为这是不正确的
所以我试着使用for
循环来实现这一点,这样第1行和第2行、第2行和第3行之间的距离就可以分别计算出来,以后再求和。我该怎么做
我的代码当前看起来像:
for(i in nrow(df)){
n <- dist(rbind(df$x,df$y))
}
我可以在以后通过跑步来总结:
sum(n)
对吗?不需要循环
dplyr
dplyr/tidyverse方法也可以覆盖多个名称(因为“名称”列的存在表示多个工作者)
df%
#按名称分组(以防DF中有多个工作人员)
#如果只有一个工人,则可以删除此行
分组单位(名称)%>%
#获取上一个x和y值
突变(x_prev=lag(x),y_prev=lag(y))%>%
#过滤掉没有上一个x值的行
过滤器(!is.na(x_prev))%>%
#计算距离
变异(距离=sqrt(绝对值(x-x\U上一个)^2+绝对值(y-y\U上一个)^2))%>%
#汇总以获得总距离
总结(总距离=总和(距离))
##A tible:1 x 2
#名称总距离
#
#约翰一世41.0
基尔
#创建x和y矩阵,计算距离并根据结果创建矩阵
Mdf
#名称x y
#1约翰12 34
#2约翰15 31
#3约翰8 38
#约翰20 14
n使用base R,您可以在每对连续的行上调用dist
,然后调用cumsum
相邻距离,以按名称获得结果
df <- read.table(text="Name x y
John 12 34
John 15 31
John 8 38
John 20 14
Mark 11 13
Mark 16 18", header=TRUE)
by(df, df$Name, function(mat) {
idx <- seq_len(nrow(mat))
cumsum(mapply(function(i,j) dist(mat[c(i,j), c("x","y")]),
head(idx, -1), tail(idx, -1)))
})
df请分享您的预期输出@ChirayuChamoli补充了我的预期结果。感谢您的反馈。您没有在循环中的任何位置使用i
。可能,您正在尝试执行,n[i]您正在执行什么距离计算?@Wimpel-Euclidean distance。我应该早点提的对不起。所以我可以使用sqrt((x[1]-x[2])^2+(y[1]-y[2])^2)这类公式,但我不知道如何进行循环。有什么帮助吗?是的,有多个worker,但是我已经为每个worker创建了一个子集,这样每个worker都有自己的数据框。所以我想我可以从mutate()部分开始?也知道没有任何NA值,我还需要使用过滤代码吗?感谢您的回复和以后的回复。@Robo NA筛选是因为您无法计算第一行的距离,因为行驶的距离基于当前和以前的x和y值。对于n
行,您将始终获得n-1
计算的抖动。尝试注释代码中的行,以查看直到该点的结果。在这个解决方案中,您不必为每个工人创建单独的子集;您可以使用组合的df和每个工作人员的组。@Robo添加了一个基本解决方案。您刚才建议的大多数功能我从未见过。谢谢你的新信息!我将尝试一下这个代码说没有叫做“I”的对象。我做错了什么?另外,R如何知道是否使用了x或y列?请你解释一下代码好吗?我对编码&R相当陌生。事实上,当我按照您的代码制作数据帧时,它确实给了我相同的结果。之前,我只是使用了另一个给定的数据集。那么,如果我要使用一个已有8000多行的数据集,我该如何模拟它呢?我不能同时为x和y写c(8000个数字)。如果我使用已经生成的数据集,它会给我一个与上面相同的错误。我在这里提到(-1)时删除了第一列的名称:df[I,-1],df[(I+1),-1]
。同样,您可以删除任何额外的列,只保留x和y列。
df <- data.frame( Name = c("John","John","John","John"),
x = c(12,15,8,20),
y = c(34,31,38,14),
stringsAsFactors = FALSE )
library(tidyverse)
df %>%
#group by name (just in case there are multiple workers in the DF)
#you can remove this line if there is only 1 worker
group_by( Name ) %>%
#get the previous x and y value
mutate( x_prev = lag( x ), y_prev = lag( y ) ) %>%
#filter out rows without previous x value
filter( !is.na( x_prev ) ) %>%
#calculate the distance
mutate( distance = sqrt( abs (x - x_prev )^2 + abs( y - y_prev )^2 ) ) %>%
#summarise to get the total distance
summarise( total_distance = sum( distance ) )
# # A tibble: 1 x 2
# Name total_distance
# <chr> <dbl>
# 1 John 41.0
#create a matrix of x and y, calculate the distance and create a matrix from the results
M <- as.matrix( dist( matrix( c( df$x, df$y ), ncol = 2 ) ) )
M
# 1 2 3 4
# 1 0.000000 4.242641 5.656854 21.54066
# 2 4.242641 0.000000 9.899495 17.72005
# 3 5.656854 9.899495 0.000000 26.83282
# 4 21.540659 17.720045 26.832816 0.00000
#get the first off diagonal of the matrix (row = column+1)
M[row(M) == col(M) + 1]
#[1] 4.242641 9.899495 26.832816
#sum the first off diagonal
sum( M[row(M) == col(M) + 1] )
#[1] 40.97495
df<-data.frame("Name" = rep(x = "John",times = 4),"x" = c(12,15,8,20),"y" = c(34,31,38,14))
#> df
# Name x y
#1 John 12 34
#2 John 15 31
#3 John 8 38
#4 John 20 14
n<-numeric()
for(i in 1:(nrow(df) - 1)){
n[i] <- dist(rbind(df[i,-1],df[(i + 1),-1]))
}
print(n)
#[1] 4.242641 9.899495 26.832816
sum(n)
#[1] 40.97495
df <- read.table(text="Name x y
John 12 34
John 15 31
John 8 38
John 20 14
Mark 11 13
Mark 16 18", header=TRUE)
by(df, df$Name, function(mat) {
idx <- seq_len(nrow(mat))
cumsum(mapply(function(i,j) dist(mat[c(i,j), c("x","y")]),
head(idx, -1), tail(idx, -1)))
})
by(df, df$Name, function(mat) {
idx <- seq_len(nrow(mat))
cumsum(
as.matrix(dist(mat[,c("x","y")]))[cbind(head(idx, -1), tail(idx, -1))])
})