R Tibble Tidying Dilemma - PullRequest
       1

R Tibble Tidying Dilemma

0 голосов
/ 08 января 2019

Я пытаюсь привести в порядок свои данные в моем R-скрипте, чтобы я мог выполнить некоторые статистические анализы на набранном массиве данных.

В одном из столбцов перечислены пары (6 из них), которые соответствуют трем отдельным «блокам» выходных значений. Минимальный воспроизводимый набор данных ниже.

dput(head(data, 6)) 
structure(list(pairs = c("ABC", "ACB", "BAC", "BCA", "CBA", "CAB"), block1vals = c(1, 3, 5, 7, 9, 10), block2vals = c(4, 66, 34, 66, 21, 21), block3vals = c(53, 22, 12, 65, 21, 22)), .Names = c("pairs", "block1vals", "block2vals", "block3vals"), row.names = c(NA, 6L), class = "data.frame")

Я получил свой код, чтобы взять пары и пометить значение A / B / C каждого участника для данного блока, столбец для каждого блока; это работает:

Блок 1:

data$block1types <- sapply(data$pairs, function(x){
  if(x == "ABC") { return("Type A")}
  if(x == "ACB") { return("Type A")}
  if(x == "BAC") { return("Type B")}
  if(x == "BCA") { return("Type B")}
  if(x == "CBA") { return("Type C")}
  if(x == "CAB") { return("Type C")}
})

Блок 2:

data$block2types <- sapply(data$pairs, function(x){
  if(x == "ABC") { return("Type B")}
  if(x == "ACB") { return("Type C")}
  if(x == "BAC") { return("Type A")}
  if(x == "BCA") { return("Type C")}
  if(x == "CBA") { return("Type B")}
  if(x == "CAB") { return("Type A")}
})

Блок 3:

data$block3types <- sapply(data$pairs, function(x){
 if(x == "ABC") { return("Type C")}
if(x == "ACB") { return("Type B")}
if(x == "BAC") { return("Type C")}
if(x == "BCA") { return("Type A")}
if(x == "CBA") { return("Type A")}
if(x == "CAB") { return("Type B")}
})

То, что я пытаюсь сделать, - это теперь реорганизовать данные так, чтобы был столбец со всеми значениями участника "Типа А" (не имеет значения, в каком блоке А был), а также один для "Типа Б" и один для «Типа С».

Итак, идеальный результат:

data$TypeA <- c(1, 3, 34, 65, 21, 21)
data$TypeB <- c(4, 22, 5, 7, 21, 22)
data$TypeC <- c(53, 66, 12, 66, 9, 10)

Я не могу понять, как это сделать без проблем. Моя попытка сделать это состояла в том, чтобы создать два столбца вне набора данных, которые, как я надеялся, я мог бы затем распространить:

BlockTypes<- combine(data$block1types, data$block2types, data$block3types, .id = NULL)     
BlockTotals<- combine(data$block1vals, data$block2vals, data$block3vals, .id = NULL) 

Затем я попытался сделать это:

spread(data, key= BlockTypes, value=BlockTotals, fill = 0)

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

Ответы [ 2 ]

0 голосов
/ 02 февраля 2019

Вот подход, использующий пакеты dplyr и stringr.

library(dplyr)
library(stringr)

data %>%
  # For each letter, determine the position of that letter in the entry in the 'pairs' column
  mutate(a = str_locate(pairs, 'A')[,'start'],
         b = str_locate(pairs, 'B')[,'start'],
         c = str_locate(pairs, 'C')[,'start']) %>% 
  # Based on the letter's position, pull the value from the appropriate column
  mutate_at(.vars = vars(a, b, c),
            .funs = funs(case_when(. == 1 ~ block1vals,
                                   . == 2 ~ block2vals,
                                   . == 3 ~ block3vals)))

Причина странного вызова str_locate() заключается в том, что вывод вызова str_locate() является матрицей.

Вот как выглядит вывод функции:

pairs <- c('ABCDE')
str_locate(pairs, 'BC')

     start end
[1,]     2   3

Чтобы вернуть только позицию буквы 'B', вам нужно извлечь столбец с названием start из матрицы.

Вы можете объединить вызов str_locate() с извлечением столбца, написав следующее:

str_locate(pairs, 'BC')['start']

0 голосов
/ 08 января 2019

Я уверен, что есть лучший способ сделать это, если я расскажу об этом, но вот что-то работает.

Сначала мы использовали функцию substr для извлечения первого, второго и третьего символов для ваших типов. Я использовал функцию вставки, чтобы включить деталь «Тип» в выполненное нами извлечение. Это намного приятнее, чем делать каждую комбинацию, как у вас.

Затем мы просмотрели данные 3 раза (по одному разу для каждого типа). Каждый раз, когда мы просматривали данные, мы использовали типы блоков, чтобы увидеть, следует ли нам извлекать значение блока.

library(tidyverse)
data <- tibble(
pairs = c("ABC", "ACB", "BAC", "BCA", "CBA", "CAB"),
block1vals = c(1, 3, 5, 7, 9, 10),
block2vals = c(4, 66, 34, 66, 21, 21),
block3vals = c(53, 22, 12, 65, 21, 22)
)

data %>%
  mutate(
    block1types = paste0("Type ",substr(pairs, 1, 1)),
    block2types = paste0("Type ",substr(pairs, 2, 2)),
    block3types = paste0("Type ",substr(pairs, 3, 3))) %>%
  mutate(
    TypeAValues = case_when(
    block1types == "Type A" ~ block1vals,
    block2types == "Type A" ~ block2vals,
    block3types == "Type A" ~ block3vals)) %>%
  mutate(
    TypeBValues = case_when(
    block1types == "Type B" ~ block1vals,
    block2types == "Type B" ~ block2vals,
    block3types == "Type B" ~ block3vals)) %>%
  mutate(
    TypeCValues = case_when(
    block1types == "Type C" ~ block1vals,
    block2types == "Type C" ~ block2vals,
    block3types == "Type C" ~ block3vals))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...