Различия между всеми возможными парами строк для всех столбцов на каждом уровне фактора - PullRequest
0 голосов
/ 13 июня 2018

Я знаю, что это распространенная проблема, но я не могу сделать эту работу.

Я хочу построить все возможные пары строк в кадре данных на каждом уровне категориальной переменной 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() 

Ответы [ 2 ]

0 голосов
/ 14 июня 2018

Я не смог выяснить, как сохранить все переменные, используя 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
0 голосов
/ 13 июня 2018

Мой образец выглядит по-другому ...

   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

Используя это и глядя здесь , мы можем сделать:

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...