请考虑以下示例:
t1 t2 t3 t4 t5 t6
A 4 6 7 8 5
A 3 6 8 1 4
A 2 3 5 3 1
A 3 4 3 1 3
B 3 6 8 3 4
B 3 9 3 7 3
B 5 2 3 2 1我希望得到一个数据帧,它检查组内每对可能的行之间的差异(A和B分别)。
我一直在尝试基于循环对数据进行子集,并手动计算行之间的差异。这导致了大量的计算,在计算了所有差异之后,很难对引用进行管理。我基本上得到了几份名单。
生成的数据文件需要包含所有可能的行组合(或排列?)的行差异。在一群人中。
例如,对于B,不考虑第一列即字符,以下是预期的结果:
t2 t3 t4 t5 t6
0 -3 5 -4 1
-2 4 5 1 3
-2 7 0 5 2 这个标志不是很重要。只有震级
发布于 2020-01-22 19:14:02
这里有一种方法可以得到一个有一行的表,它显示了每个组中每对行之间的差异。例如,该输出的第2行显示输入的第1行减去输入的第3行。
library(data.table)
setDT(df) # convert to data.table
df[, { pairs <- CJ(row1 = 1:.N, row2 = 1:.N)[row1 != row2]
data.table(pairs + .I[1] - 1, .SD[pairs[[1]]] - .SD[pairs[[2]]])
}, by = t1]
# t1 row1 row2 t2 t3 t4 t5 t6
# 1: A 1 2 1 0 -1 7 1
# 2: A 1 3 2 3 2 5 4
# 3: A 1 4 1 2 4 7 2
# 4: A 2 1 -1 0 1 -7 -1
# 5: A 2 3 1 3 3 -2 3
# 6: A 2 4 0 2 5 0 1
# 7: A 3 1 -2 -3 -2 -5 -4
# 8: A 3 2 -1 -3 -3 2 -3
# 9: A 3 4 -1 -1 2 2 -2
# 10: A 4 1 -1 -2 -4 -7 -2
# 11: A 4 2 0 -2 -5 0 -1
# 12: A 4 3 1 1 -2 -2 2
# 13: B 5 6 0 -3 5 -4 1
# 14: B 5 7 -2 4 5 1 3
# 15: B 6 5 0 3 -5 4 -1
# 16: B 6 7 -2 7 0 5 2
# 17: B 7 5 2 -4 -5 -1 -3
# 18: B 7 6 2 -7 0 -5 -2这有点多余,因为它还显示了第3行-第1行(这只是负数)。如果不希望复制,请将row1 != row2更改为row1 < row2。
df[, { pairs <- CJ(row1 = 1:.N, row2 = 1:.N)[row1 < row2]
data.table(pairs + .I[1] - 1, .SD[pairs[[1]]] - .SD[pairs[[2]]])
}, by = t1]
# t1 row1 row2 t2 t3 t4 t5 t6
# 1: A 1 2 1 0 -1 7 1
# 2: A 1 3 2 3 2 5 4
# 3: A 1 4 1 2 4 7 2
# 4: A 2 3 1 3 3 -2 3
# 5: A 2 4 0 2 5 0 1
# 6: A 3 4 -1 -1 2 2 -2
# 7: B 5 6 0 -3 5 -4 1
# 8: B 5 7 -2 4 5 1 3
# 9: B 6 7 -2 7 0 5 2解释:
CJ(a, b)为所有可能的值对(ai,bj)生成一行的data.table。示例:
CJ(1:3, 1:3)
# V1 V2
# 1: 1 1
# 2: 1 2
# 3: 1 3
# 4: 2 1
# 5: 2 2
# 6: 2 3
# 7: 3 1
# 8: 3 2
# 9: 3 3因为它是一个data.table,所以您可以通过在[]中使用非$前缀的列名进行子集,例如
CJ(a = 1:3, b = 1:3)[a < b]
# a b
# 1: 1 2
# 2: 1 3
# 3: 2 3在j部分的dt[i, j, k]中,变量.SD是给定组的整个data.table子集(由k中的分组vars确定的组)。因此,这个答案接受每对元素的第一个元素,选择与这些元素.SD[pairs[[1]]]对应的组的行,并从中减去组中对应于每对.SD[pairs[[2]]]的其他元素的行。一个data.table是用pairs和这个减法的输出创建的。这是为每个组完成的,data.table会自动将所有组输出合并在一起。
发布于 2020-01-22 19:20:05
使用tidyverse,您可以在每个t1中使用笛卡尔连接。
dat %>%
gather(key, value, -grp) %>%
left_join(gather(dat, key, value, - grp), by = "grp") %>%
mutate(diff = value.x - value.y)
grp key.x value.x key.y value.y diff
1 A t2 4 t2 4 0
2 A t2 4 t2 3 1
3 A t2 4 t2 2 2
4 A t2 4 t2 3 1
5 A t2 4 t3 6 -2
6 A t2 4 t3 6 -2注意,由于我的大脑并不总是遵守规则,所以我将t1重新命名为grp。
发布于 2020-01-22 19:31:45
这是一个选择。我们将数据按组拆分,然后找到每个组的每一个行组合,然后映射出差异并重新连接。
library(tidyverse)
testDat %>%
group_by(t1) %>%
mutate(row = row_number()) %>%
split(.$t1) %>%
map(
~nest(., data = -c(t1, row)) %>%
list(.,.) %>%
reduce(full_join, by = "t1") %>%
rename(row1 = row.x, row2 = row.y, vec1 = data.x, vec2 = data.y) %>%
filter(row1 != row2) %>%
mutate(diff = map2(vec1, vec2, ~unlist(.x)-unlist(.y)))%>%
select(-vec1, -vec2) %>%
unnest_wider(col = diff)
) %>%
bind_rows()
#> # A tibble: 18 x 8
#> # Groups: t1 [2]
#> t1 row1 row2 t2 t3 t4 t5 t6
#> <chr> <int> <int> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1 A 1 2 1 0 -1 7 1
#> 2 A 1 3 2 3 2 5 4
#> 3 A 1 4 1 2 4 7 2
#> 4 A 2 1 -1 0 1 -7 -1
#> 5 A 2 3 1 3 3 -2 3
#> 6 A 2 4 0 2 5 0 1
#> 7 A 3 1 -2 -3 -2 -5 -4
#> 8 A 3 2 -1 -3 -3 2 -3
#> 9 A 3 4 -1 -1 2 2 -2
#> 10 A 4 1 -1 -2 -4 -7 -2
#> 11 A 4 2 0 -2 -5 0 -1
#> 12 A 4 3 1 1 -2 -2 2
#> 13 B 1 2 0 -3 5 -4 1
#> 14 B 1 3 -2 4 5 1 3
#> 15 B 2 1 0 3 -5 4 -1
#> 16 B 2 3 -2 7 0 5 2
#> 17 B 3 1 2 -4 -5 -1 -3
#> 18 B 3 2 2 -7 0 -5 -2https://stackoverflow.com/questions/59866405
复制相似问题