每个因子水平内所有列的所有可能行对之间的差异
Differences between all possible pairs of rows for all columns within each level of factor
我知道这是一个常见问题,但我做不到。
我想在分类变量name
的每个级别内的数据帧中构建所有可能的行对并且然后对所有非因子变量在 name
的每个级别内对这些行进行差分:第 1 行 - 第 2 行,第 1 行 - 第 3 行,...
set.seed(9)
df <- data.frame(ID = 1:10,
name=as.factor(rep(LETTERS, each=4)[1:10]),
X1 = sample(1001, 10),
X2 = sample(1001, 10),
bool=sample(c(TRUE, FALSE), 10, replace = TRUE),
fruit = as.factor(sample(c("Apple", "Orange", "Kiwi" ), 10, replace = TRUE)))
示例如下所示:
ID name X1 X2 bool fruit
1 1 A 222 118 FALSE Apple
2 2 A 25 9 TRUE Kiwi
3 3 A 207 883 TRUE Orange
4 4 A 216 301 TRUE Kiwi
5 5 B 443 492 FALSE Apple
6 6 B 134 499 FALSE Kiwi
7 7 B 389 401 TRUE Kiwi
8 8 B 368 972 TRUE Kiwi
9 9 C 665 356 FALSE Apple
10 10 C 985 488 FALSE Kiwi
我想要一个 13 行的数据框,如下所示:
ID name X1 X2 bool fruit
1 1-2 A 197 109 -1 Apple
2 1-3 A 15 -765 -1 Kiwi
…
请注意,因子 fruit
应该保持不变。但这是一个奖励,我首先要更改 X1
和 X2
并保留 name
因素。
我知道我可以使用 combn
功能,但我不知道该怎么做。我更喜欢使用 dplyr
包和 group_by
函数的解决方案。
我已经设法用 dplyr
使用
为连续行创建所有差异
varnotfac <- names(df)[!sapply(df, is.factor )] # remove factorial variable
# but not logical variable
library(dplyr)
diff <- df%>%
group_by(name) %>%
mutate_at(varnotfac, funs(. - lead(.))) %>% #
na.omit()
我的样品看起来不一样...
ID name X1 X2 bool
1 1 A 222 118 FALSE
2 2 A 25 9 TRUE
3 3 A 207 883 TRUE
4 4 A 216 301 TRUE
5 5 B 443 492 FALSE
6 6 B 134 499 FALSE
7 7 B 389 401 TRUE
8 8 B 368 972 TRUE
9 9 C 665 356 FALSE
10 10 C 985 488 FALSE
使用这个,并寻找 here,我们可以做:
library(dplyr)
library(tidyr)
library(purrr)
df %>%
group_by(name) %>%
nest() %>%
mutate(data = map(data, ~as.data.frame(map(.x, ~as.numeric(dist(.)))))) %>%
unnest()
# A tibble: 13 x 5
name ID X1 X2 bool
<fct> <dbl> <dbl> <dbl> <dbl>
1 A 1 197 109 1
2 A 2 15 765 1
3 A 3 6 183 1
4 A 1 182 874 0
5 A 2 191 292 0
6 A 1 9 582 0
7 B 1 309 7 0
8 B 2 54 91 1
9 B 3 75 480 1
10 B 1 255 98 1
11 B 2 234 473 1
12 B 1 21 571 0
13 C 1 320 132 0
虽然这是未签名的。或者:
df %>%
group_by(name) %>%
nest() %>%
mutate(data = map(data, ~as.data.frame(map(.x, ~combn(., 2, diff))))) %>%
unnest()
# A tibble: 13 x 5
name ID X1 X2 bool
<fct> <int> <int> <int> <int>
1 A 1 -197 -109 1
2 A 2 -15 765 1
3 A 3 -6 183 1
4 A 1 182 874 0
5 A 2 191 292 0
6 A 1 9 -582 0
7 B 1 -309 7 0
8 B 2 -54 -91 1
9 B 3 -75 480 1
10 B 1 255 -98 1
11 B 2 234 473 1
12 B 1 -21 571 0
13 C 1 320 132 0
我无法找到如何使用 filter_if
/ filter_at
保留所有变量,所以我使用了 select_at
。所以来自@Axeman 的回答
set.seed(9)
varnotfac <- names(df)[!sapply(df, is.factor )] # names of non-factorial variables
diff1<- df %>%
group_by(name) %>%
select_at(vars(varnotfac)) %>%
nest() %>%
mutate(data = purrr::map(data, ~as.data.frame(map(.x, ~combn(., 2, base::diff))))) %>%
unnest()
或者使用 outer
函数,它比 combn
快多了
set.seed(9)
varnotfac <- names(df)[!sapply(df, is.factor )] # names of non-factorial variables
allpairs <- function(v){
y <- outer(v,v,'-')
z <- y[lower.tri(y)]
return(z)
}
diff2<- df %>%
group_by(name) %>%
select_at(vars(varnotfac)) %>%
nest() %>%
mutate(data = purrr::map(data, ~as.data.frame(map(.x, ~allpairs(.))))) %>%
unnest()
)
可以检查得到的data.frame和
是一样的
all.equal(diff1,diff2)
[1] TRUE
我知道这是一个常见问题,但我做不到。
我想在分类变量name
的每个级别内的数据帧中构建所有可能的行对并且然后对所有非因子变量在 name
的每个级别内对这些行进行差分:第 1 行 - 第 2 行,第 1 行 - 第 3 行,...
set.seed(9)
df <- data.frame(ID = 1:10,
name=as.factor(rep(LETTERS, each=4)[1:10]),
X1 = sample(1001, 10),
X2 = sample(1001, 10),
bool=sample(c(TRUE, FALSE), 10, replace = TRUE),
fruit = as.factor(sample(c("Apple", "Orange", "Kiwi" ), 10, replace = TRUE)))
示例如下所示:
ID name X1 X2 bool fruit
1 1 A 222 118 FALSE Apple
2 2 A 25 9 TRUE Kiwi
3 3 A 207 883 TRUE Orange
4 4 A 216 301 TRUE Kiwi
5 5 B 443 492 FALSE Apple
6 6 B 134 499 FALSE Kiwi
7 7 B 389 401 TRUE Kiwi
8 8 B 368 972 TRUE Kiwi
9 9 C 665 356 FALSE Apple
10 10 C 985 488 FALSE Kiwi
我想要一个 13 行的数据框,如下所示:
ID name X1 X2 bool fruit
1 1-2 A 197 109 -1 Apple
2 1-3 A 15 -765 -1 Kiwi
…
请注意,因子 fruit
应该保持不变。但这是一个奖励,我首先要更改 X1
和 X2
并保留 name
因素。
我知道我可以使用 combn
功能,但我不知道该怎么做。我更喜欢使用 dplyr
包和 group_by
函数的解决方案。
我已经设法用 dplyr
使用
varnotfac <- names(df)[!sapply(df, is.factor )] # remove factorial variable
# but not logical variable
library(dplyr)
diff <- df%>%
group_by(name) %>%
mutate_at(varnotfac, funs(. - lead(.))) %>% #
na.omit()
我的样品看起来不一样...
ID name X1 X2 bool 1 1 A 222 118 FALSE 2 2 A 25 9 TRUE 3 3 A 207 883 TRUE 4 4 A 216 301 TRUE 5 5 B 443 492 FALSE 6 6 B 134 499 FALSE 7 7 B 389 401 TRUE 8 8 B 368 972 TRUE 9 9 C 665 356 FALSE 10 10 C 985 488 FALSE
使用这个,并寻找 here,我们可以做:
library(dplyr)
library(tidyr)
library(purrr)
df %>%
group_by(name) %>%
nest() %>%
mutate(data = map(data, ~as.data.frame(map(.x, ~as.numeric(dist(.)))))) %>%
unnest()
# A tibble: 13 x 5 name ID X1 X2 bool <fct> <dbl> <dbl> <dbl> <dbl> 1 A 1 197 109 1 2 A 2 15 765 1 3 A 3 6 183 1 4 A 1 182 874 0 5 A 2 191 292 0 6 A 1 9 582 0 7 B 1 309 7 0 8 B 2 54 91 1 9 B 3 75 480 1 10 B 1 255 98 1 11 B 2 234 473 1 12 B 1 21 571 0 13 C 1 320 132 0
虽然这是未签名的。或者:
df %>%
group_by(name) %>%
nest() %>%
mutate(data = map(data, ~as.data.frame(map(.x, ~combn(., 2, diff))))) %>%
unnest()
# A tibble: 13 x 5 name ID X1 X2 bool <fct> <int> <int> <int> <int> 1 A 1 -197 -109 1 2 A 2 -15 765 1 3 A 3 -6 183 1 4 A 1 182 874 0 5 A 2 191 292 0 6 A 1 9 -582 0 7 B 1 -309 7 0 8 B 2 -54 -91 1 9 B 3 -75 480 1 10 B 1 255 -98 1 11 B 2 234 473 1 12 B 1 -21 571 0 13 C 1 320 132 0
我无法找到如何使用 filter_if
/ filter_at
保留所有变量,所以我使用了 select_at
。所以来自@Axeman 的回答
set.seed(9)
varnotfac <- names(df)[!sapply(df, is.factor )] # names of non-factorial variables
diff1<- df %>%
group_by(name) %>%
select_at(vars(varnotfac)) %>%
nest() %>%
mutate(data = purrr::map(data, ~as.data.frame(map(.x, ~combn(., 2, base::diff))))) %>%
unnest()
或者使用 outer
函数,它比 combn
set.seed(9)
varnotfac <- names(df)[!sapply(df, is.factor )] # names of non-factorial variables
allpairs <- function(v){
y <- outer(v,v,'-')
z <- y[lower.tri(y)]
return(z)
}
diff2<- df %>%
group_by(name) %>%
select_at(vars(varnotfac)) %>%
nest() %>%
mutate(data = purrr::map(data, ~as.data.frame(map(.x, ~allpairs(.))))) %>%
unnest()
)
可以检查得到的data.frame和
是一样的all.equal(diff1,diff2)
[1] TRUE