【问题标题】:R - Reshape long to wide, grouping by two variablesR - 从长到宽,按两个变量分组
【发布时间】:2020-06-22 15:51:31
【问题描述】:

我有一个名为 result 的数据框,它有 4 列(x,y,标签,NN.idx 和 dist),分别代表平面中观察的位置,一个用于避免 (x,y) 重复的标签(参见我在下面的评论)它最近邻居在另一个数据帧中的索引和到它的距离。 备注:每个 (x,y) 组合可能出现一到三次,如果出现,则通过不同的标签来区分它们(例如第 1,4 和 5 行以及下面的示例)。另外,请注意,两个不同的点可能具有相同的标签,这是我从之前的数据操作中计算出来的数量,例如第 1 行和第 3 行都有相同的标签,但它们显然不代表同一个点 (x,y)。

这是一个例子:


result <- data.frame(x=c(0.147674, 0.235356 ,0.095337, 0.147674, 0.147674, 1.000000, 2.000000), y=c(0.132956, 0.150813, 0.087345, 0.132956, 0.132956, 2.000000, 1.000000), label = c(5,6,5,6,7,3,9), NN.idx =c(4325,2703,21282,3460,12,4,10), dist=c(0.02391247,0.03171236,0.01760940,0.03136304, 0.02315468, 0.01567365, 0.02314860))

head(result)

         x        y        label NN.idx        dist
1 0.147674 0.132956            5   4325  0.02391247
2 0.235356 0.150813            6   2703  0.03171236
3 0.095337 0.087345            5  21282  0.01760940
4 0.147674 0.132956            6   3460  0.03136304
5 0.147674 0.132956            7     12  0.02315468
6 1.000000 2.000000            3      4  5.00000000
7 2.000000 1.000000            9     10 11.00000000

我想做的是非常有效地将此数据帧(实际数据帧大得多)重塑为宽格式,其中每一行对应于一个 unique (x,y) 组合,并且会当前列 NN.idx_1、NN.idx_2、NN.idx_3、dist_1、dist_2、dist_3 给出原始数据帧中每次出现的 (x,y) 组合的 NN.idx 和 dist(如果 (x ,y) 组合只出现两次或一次)

我对 R 比较陌生,只知道基础知识,但我想我可能有一个使用 data.tabledcast 的解决方案,如下所示:

df <- setDT(result)
df[,NN.counter := 1:.N, by=c("x","y")]
df <- dcast(df, x+y~ NN.counter, value.var=c("NN.idx","dist"))

head(df)

        x        y   NN.idx_1 NN.idx_2 NN.idx_3     dist_1     dist_2     dist_3
1: 0.095337 0.087345    21282       NA       NA 0.01760940         NA         NA
2: 0.147674 0.132956     4325     3460       12 0.02391247 0.03136304 0.02315468
3: 0.235356 0.150813     2703       NA       NA 0.03171236         NA         NA
4: 1.000000 2.000000        4       NA       NA 0.01567365         NA         NA
5: 2.000000 1.000000       10       NA       NA 0.02314860         NA         NA


我的问题如下:我的方法好吗?我不熟悉 dcast 和符号 x+y ~ NN.counter 让我想知道导致相同总和 x+y 的两个不同点 (x,y) 是否会被视为不同(例如,我的原始数据帧的第 6 行和第 7 行,其中 x 和 y 颠倒)。显然它似乎有效。

有没有人有更好的方法来处理这个重复的问题,或者我的可以吗?另外,我不知道这是否相当快,尽管我读过data.table 相当快。

【问题讨论】:

  • 顺便说一句,+ 在公式中是术语的分隔符,它不是算术加法。也可以直接在公式dcast(setDT(result), x + y ~ rowid(x, y), value.var=c("NN.idx","dist"))中使用rowid

标签: r data.table reshape


【解决方案1】:

由于xy 都是numeric,您可能会遇到基于浮点精度的问题(即R FAQ 7.31IEEE-754)。虽然它可能有效,但我不知道我会严格依赖它(没有大量验证)。在分组和dcasting 之前强制转换为固定长度的字符串(例如sprintf("%0.06f", x))可能很有用(为了重塑)。

这里有一个想法可以解决这个问题。 (注意:我使用magrittr 仅用于通过%&gt;% 管道中断步骤,它不需要起作用。)

library(data.table)
library(magrittr)
result <- data.table(x=c(0.147674, 0.235356 ,0.095337, 0.147674, 0.147674, 1.000000, 2.000000), y=c(0.132956, 0.150813, 0.087345, 0.132956, 0.132956, 2.000000, 1.000000), label = c(5,6,5,6,7,3,9), NN.idx =c(4325,2703,21282,3460,12,4,10), dist=c(0.02391247,0.03171236,0.01760940,0.03136304, 0.02315468, 0.01567365, 0.02314860))

result[, c("x_s", "y_s") := lapply(.(x, y), sprintf, fmt = "%0.09f") ]
savexy <- unique(result[, .(x, y, x_s, y_s) ]) # merge back in later with "real" numbers
result2 <- copy(result) %>%
  .[, c("x", "y") := NULL ] %>%
  .[, NN.counter := seq_len(.N), by = c("x_s", "y_s") ] %>%
  dcast(x_s + y_s ~ NN.counter, value.var = c("NN.idx", "dist") ) %>%
  merge(., savexy, by = c("x_s", "y_s"), all.x = TRUE) %>%
  .[, c("x_s", "y_s") := NULL ] %>%
  setcolorder(., c("x", "y"))
result2
#           x        y NN.idx_1 NN.idx_2 NN.idx_3     dist_1     dist_2     dist_3
# 1: 0.095337 0.087345    21282       NA       NA 0.01760940         NA         NA
# 2: 0.147674 0.132956     4325     3460       12 0.02391247 0.03136304 0.02315468
# 3: 0.235356 0.150813     2703       NA       NA 0.03171236         NA         NA
# 4: 1.000000 2.000000        4       NA       NA 0.01567365         NA         NA
# 5: 2.000000 1.000000       10       NA       NA 0.02314860         NA         NA

【讨论】:

  • 没想到浮点精度!非常感谢您的回答!
猜你喜欢
  • 2019-03-14
  • 1970-01-01
  • 2014-05-12
  • 1970-01-01
  • 2018-01-14
  • 1970-01-01
  • 2018-05-05
  • 1970-01-01
相关资源
最近更新 更多