我知道这是一个常见的问题,但我无法做到这一点。
我想在分类变量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()
答案 0 :(得分:1)
我无法找到如何使用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
答案 1 :(得分:0)
我的样本看起来不一样......
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