【问题标题】:Adding values based on levels of a factor基于因子水平添加值
【发布时间】:2015-08-20 20:25:41
【问题描述】:

我有这个可重复的 data.frame 代表五个人 (IndID) 的 UTM 位置,每个人都有 20 个位置

编辑:不同的答案似乎是由于在未排序的data.frame. 上运行我的for() 循环我已将代码添加到arrange IndID 的df,现在得到相同的结果像你一样回答。

library(plyr)

set.seed(123)
Data <- data.frame(IndID = rep(c("AAA", "BBB", "CCC", "DDD", "EEE"), 20),
                UTM_E = sample(482000:509000, 100),
                UTM_N = sample(4780000:4810500, 100)
                    )

Data <- arrange(Data, IndID)

我也有这张表,其中包含每个人的单个 Start 位置。

set.seed(123)
Start <- data.frame(IndID = c("AAA", "BBB", "CCC", "DDD", "EEE"),
                UTM_E = sample(482000:509000, 5),
                UTM_N = sample(4780000:4810500, 5)
                    )

对于每个级别的 IndID 我想应用以下计算在Data. 中添加一个新列例如,当Data$IndID == Start$IndID 我想创建时

Data$NewValue = ((((Data$UTM_E - Start$UTM_E)/1000)^2) + (((Data$UTM_N - Start$UTM_N)/1000)^2))

虽然我知道使用以下 for() 循环和格式化代码可以做到这一点,但我怀疑有更好的向量方法可以更清洁、更高效。

Inds <- unique(Data$IndID)
NewValue <- list()
for (i in 1:length(Inds)){
    NewValue[[i]] = ((((Data$UTM_E[Data$IndID == Inds[i]] - Start$UTM_E[i])/1000)^2) + 
            (((Data$UTM_N[Data$IndID == Inds[i]] - Start$UTM_N[i])/1000)^2))
                    }

Data$NewValue <- c(do.call("cbind",NewValue)) 

head(Data)
tail(Data)

任何关于如何“矢量化”上述for() 循环的建议将不胜感激。

【问题讨论】:

  • 附注:如果您正在分析动物运动,您可以查看adehabitatLT 包。很容易从像你这样的时空数据中获取基本指标。参见例如the vignette.
  • @Henrik。是的,adehabitatLT 包很棒,但对于当前项目,最好使用 ltraj 对象格式。

标签: r for-loop vectorization


【解决方案1】:

我们可以使用merge 制作一个data.frame,然后从那里向量化:

data2 <- merge(Data, Start, by = "IndID")
data2$NewValue <- ((data2$UTM_E.x - data2$UTM_E.y)/1000)^2 + 
                  ((data2$UTM_N.x - data2$UTM_N.y)/1000)^2

【讨论】:

  • 您是否能够获得与 OP 相同的值?我和你的一样,和他的很不一样。这就是我没有发帖的原因。
  • 哦,你是对的 - 我检查的第一个和最后一个值是相同的
  • "打电话给我只发现另一个孤儿"
  • @David Arenburg 它们是相同的 - 行只是顺序不同
  • 不可能。我在 OPs NewValue 之后创建了 NewValue2 以便进行比较。而且它们不是按行匹配的。
【解决方案2】:

我建议使用data.tables 二进制连接和按引用更新任务的功能

library(data.table)
setkey(setDT(Data), IndID)[Start, NewValue := ((UTM_E - i.UTM_E)/1e3)^2 + 
                                              ((UTM_N - i.UTM_N)/1e3)^2] 

注意我和@jeremycg 从你那里得到不同的结果。您的计算似乎有些错误。


这里的想法是按公共列键。执行二元连接,并在连接时使用:= 更新NewValue 列。列名前的i. 用于区分DataStart 中的相同列

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多