условно транспонировать выбранные строки, используя Tidyverse - PullRequest
2 голосов
/ 27 сентября 2019

У меня есть набор данных, с которым я работаю, и пытаюсь изменить форму, используя tidyverse.

От:

|Name |eval   |test |type      | score|
|:----|:------|:----|:---------|-----:|
|John |first  |1    |pretest   |    10|
|John |first  |1    |posttest  |    15|
|John |first  |2    |pretest   |    20|
|John |first  |2    |posttest |    30|
|John |second |1    |pretest   |    35|
|John |second |1    |posttest  |    50|
|John |second |2    |pretest   |     5|
|John |second |2    |posttest |    10|
|Jane |first  |1    |pretest   |    40|
|Jane |first  |1    |posttest  |    20|
|Jane |first  |2    |pretest   |    10|
|Jane |first  |2    |posttest |    20|

До:

|Name |eval   |new_name      | pre_test| post_test|
|:----|:------|:-------------|--------:|---------:|
|John |first  |John_first_1  |       10|        15|
|John |first  |John_first_2  |       20|        30|
|John |second |John_second_1 |       35|        50|
|John |second |John_second_2 |        5|        10|
|Jane |first  |Jane_first_1  |       40|        20|
|Jane |first  |Jane_first_2  |       10|        20|
  • попытался сделать group_by для group_by Имя, evalи проверьте, чтобы каждая группа по существу была pre_test против post_test для данного человека.

  • также пытался использовать unite для Name, eval, test и type,Но если я сделаю спред после этого, то каждое уникальное имя будет представлять собой столбцы.

  • также попытался сделать объединить сначала по имени, по eval, сначала по тесту, а затем спред , используя ключ = (новое объединенное имя) и значение = значение, но вывод не тот, который я хотел

Я знаю, что функция цикла может быть написана так, чтобы она принимала каждое другое значение и помещалась в новый столбец, но я пытаюсь выяснить, есть ли способ tidyverse , чтобы это сделать.

Спасибо !!

library(tidyverse)
Name <- c('John', 'John', 'John', 'John',
              'John', 'John', 'John', 'John',
              'Jane', 'Jane', 'Jane', 'Jane')
eval <- c('first', 'first', 'first', 'first',
          'second', 'second', 'second', 'second',
          'first', 'first', 'first', 'first')
test <- c('1', '1', '2', '2',
          '1', '1', '2', '2',
          '1', '1', '2', '2')
type <- c('pretest', 'posttest', 'pretest', 'posttest',
          'pretest', 'posttest', 'pretest', 'posttest',
          'pretest', 'posttest', 'pretest', 'posttest')
score <- c(10, 15, 20, 30, 35, 50, 5, 10, 40, 20, 10, 20)
df <- data.frame(Name, eval, test, type, score)

df %>%
  unite(temp, Name, eval, test) %>%
  spread(key=type, value=score)

Отредактируйте, чтобы показать исходную таблицу, над которой работал код akrun С:

|Name |eval   |test |type      | score|
|:----|:------|:----|:---------|-----:|
|John |first  |1    |pretest   |    10|
|John |first  |1    |posttest  |    15|
|John |first  |2    |pretest   |    20|
|John |first  |2    |postttest |    30|
|John |second |1    |pretest   |    35|
|John |second |1    |posttest  |    50|
|John |second |2    |pretest   |     5|
|John |second |2    |postttest |    10|
|Jane |first  |1    |pretest   |    40|
|Jane |first  |1    |posttest  |    20|
|Jane |first  |2    |pretest   |    10|
|Jane |first  |2    |postttest |    20|

Ответы [ 2 ]

2 голосов
/ 27 сентября 2019

Как насчет чего-то вроде ....

data <- tibble(
  Name = c(rep("John", 8), rep("Jane", 4)),
  eval = c(rep("first", 4), rep("second", 4), rep("first", 4)),
  type = rep(c("pretest", "posttest"), 6),
  score = c(10, 15, 20, 30, 35, 50, 5, 10, 40, 20, 10, 20)
)

data %>% 
  group_by(Name, eval, type) %>% 
  mutate(num = 1:n(),
         new_name = str_c(Name, "_", eval, "_", num)) %>% 
  ungroup()  %>% 
  dplyr::select(new_name, type, score) %>% 
  spread(type, score) 

Что дает:

# A tibble: 6 x 3
  new_name      posttest pretest
  <chr>            <dbl>   <dbl>
1 Jane_first_1        20      40
2 Jane_first_2        20      10
3 John_first_1        15      10
4 John_first_2        30      20
5 John_second_1       50      35
6 John_second_2       10       5
2 голосов
/ 27 сентября 2019

Мы можем заменить несколько 't в столбце' type ', чтобы сделать его одинаковым, затем использовать unite, указать remove = FALSE, чтобы сохранить и исходные столбцы, и spread

library(dplyr)
library(tidyr)
library(stringr)
df %>% 
   mutate(type = str_replace(type, "t{2,}", "t")) %>%
   unite(new_name, Name, eval, test, remove = FALSE) %>% 
   spread(type, score)
#       new_name Name   eval test postest pretest
#1  Jane_first_1 Jane  first    1      20      40
#2  Jane_first_2 Jane  first    2      20      10
#3  John_first_1 John  first    1      15      10
#4  John_first_2 John  first    2      30      20
#5 John_second_1 John second    1      50      35
#6 John_second_2 John second    2      10       5

В новой версии tidyr_1.0.0 введено pivot_wider, и его можно использовать в качестве более обобщенной версии spread (в будущем не рекомендуется).Таким образом, вместо строки spread в конце используйте

 ...%>%
    pivot_wider(names_from = type, values_from = score)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...