для цикла с функцией, которая записывает в 3 отдельных столбца решение R или dplyr/reshape?

Я новичок в циклах for, поэтому прошу прощения, если на этот вопрос уже есть четкий ответ, но я не смог найти ничего, что я понял, как применить к этому конкретному вопросу. Я также начал пробовать реализацию dplyr в конце, но тоже не смог понять.

Вот мой вопрос: есть функция, которая получает 3 значения из вектора. Я хотел бы записать эти 3 значения в тот же df, что и новые столбцы. Функция timefit из библиотеки retimes в R. Если я запускаю ее на всем df:

  a1 <-  timefit(data$RT)
  a1:
        mu: 480.3346 
     sigma: 77.8531 
       tau: 376.7426 

Если я помещу значения в df df <- data.frame(a1@par):

      a1.par
mu    480.33462
sigma 77.85305
tau   376.74257

Я хотел бы запустить его отдельно для каждого subID на основе другой переменной «местоположение» (фактор с двумя уровнями). Так что я получаю что-то вроде

subID location mu sigma tau
1      0        500 50   400
1      0        500 50   400
1      1        376 50   410
1      1        376 50   410
2      0        400 60   400
2      0        400 60   400
2      1        410 60   410  
2      1        410 60   410

я начал с

for (subID in data) {
  timefit(data$RT)
}

Но я знаю, что на самом деле это не будет делать то, что мне нужно. Значения извлекаются из модели timefit с помощью @par в длинный формат, поэтому мне нужно указать timefit функции для записи в 3 отдельных заголовка столбцов? Какие-либо предложения?

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

data <- data %>% 
  group_by(subID, location) %>%
  mutate(timefit_out = timefit(RT))

Спасибо за вашу помощь!


person Mik    schedule 10.10.2016    source источник


Ответы (2)


Вы можете использовать здесь summarise вместо mutate для создания столбца-списка, содержащего data.frame из timefit каждого (subID, location). Эти кадры данных кодируют mu, sigma и tau из результата timefit в виде столбцов. Затем используйте unnest, чтобы удалить этот столбец списка, чтобы получить желаемый результат.

library(retimes)
library(dplyr)
library(tidyr)
result <- data %>% group_by(subID, location) %>%
                   summarise(timefit_out = list(data.frame(t(attr(timefit(RT),"par"))))) %>%
                   unnest()

Обратите внимание, что мы извлекаем атрибут "par" из класса timefit, а затем транспонируем его с t для формирования столбцов для mu, sigma и tau.

Здесь мы предполагаем, что ваши входные данные data представляют собой фрейм данных со столбцами subID, location и числовым столбцом времени реакции RT, который вводится в timefit. Смоделированный пример такого набора данных представлен следующим образом:

data <- structure(list(subID = c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 
2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L), 
location = c(0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 1L, 
1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 0L, 0L, 0L, 0L, 0L, 0L, 
0L, 0L, 0L, 0L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L), 
RT = c(0.341764254728332, 0.775535081513226, 0.281827432336286, 
0.23970171622932, 0.00226009078323841, 0.385179498931393, 
0.645917195128277, 0.812101020244882, 0.183301427634433, 
0.981765420176089, 0.656369511503726, 0.824469136772677, 
0.923240559641272, 0.598261737963185, 0.309975759591907, 
0.778991278028116, 0.757012664806098, 0.869985132943839, 
0.439378245733678, 0.8420404586941, 0.643788777757436, 0.381316626211628, 
0.123881611274555, 0.540528740268201, 0.661961955949664, 
0.0592848095111549, 0.904047027230263, 0.190083365887403, 
0.963809312786907, 0.0925120878964663, 0.117538752267137, 
0.451085010776296, 0.703220259631053, 0.378451474476606, 
0.305718191433698, 0.70383172808215, 0.699415655340999, 0.740436099236831, 
0.429179352009669, 0.205358384409919)), .Names = c("subID", 
"location", "RT"), row.names = c(NA, 40L), class = "data.frame")
##   subID location          RT
##1      1        0 0.341764255
##2      1        0 0.775535082
##3      1        0 0.281827432
##4      1        0 0.239701716
##5      1        0 0.002260091
##6      1        0 0.385179499
##7      1        0 0.645917195
##8      1        0 0.812101020
##9      1        0 0.183301428
##10     1        0 0.981765420
##11     1        1 0.656369512
##12     1        1 0.824469137
##13     1        1 0.923240560
##14     1        1 0.598261738
##15     1        1 0.309975760
##16     1        1 0.778991278
##17     1        1 0.757012665
##18     1        1 0.869985133
##19     1        1 0.439378246
##20     1        1 0.842040459
##21     2        0 0.643788778
##22     2        0 0.381316626
##23     2        0 0.123881611
##24     2        0 0.540528740
##25     2        0 0.661961956
##26     2        0 0.059284810
##27     2        0 0.904047027
##28     2        0 0.190083366
##29     2        0 0.963809313
##30     2        0 0.092512088
##31     2        1 0.117538752
##32     2        1 0.451085011
##33     2        1 0.703220260
##34     2        1 0.378451474
##35     2        1 0.305718191
##36     2        1 0.703831728
##37     2        1 0.699415655
##38     2        1 0.740436099
##39     2        1 0.429179352
##40     2        1 0.205358384

Значения для RT в этом примере генерируются с использованием runif, поэтому они находятся между 0 и 1. Ваши ценности сильно отличаются, но здесь это не должно иметь значения.

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

print(result)
##Source: local data frame [4 x 5]
##Groups: subID [2]
##
##  subID location        mu     sigma         tau
##  <int>    <int>     <dbl>     <dbl>       <dbl>
##1     1        0 0.5275058 0.2553621 0.007086207
##2     1        1 0.2609386 0.1583494 0.085449559
##3     2        0 0.5205647 0.1994942 0.027329115
##4     2        1 0.4632886 0.2881343 0.008026460
person aichao    schedule 10.10.2016
comment
Отлично, спасибо. Также хотел добавить, что сводка была замаскирована для меня (не знаю точно, почему), но если бы я не указывал, dplyr::summarise возвращал только общую строку. - person Mik; 10.10.2016
comment
@MikaelRubin: это может быть из-за plyr, как вы упомянули, что работали с ddply. Вы можете detach и plyr, и dplyr, а затем загрузить dplyr. Если вам нужны оба пакета, обязательно сначала загрузите plyr, а затем dplyr. - person aichao; 10.10.2016

То, что вы, вероятно, ищете, если вы ищете dplyr решение, это do. Это позволяет возвращать data.frames, хотя может потребоваться небольшая манипуляция. В частности, он предназначен для работы с группами, а не (обязательно) со строками. Итак, вам придется установить группы, если вы хотите, чтобы он возвращался с некоторой исходной информацией (и в зависимости от структуры вашей функции).

Для этого я создаю простой набор данных:

myData <-
  data.frame(
    RT = 1:4
  )

Вам также потребуется создать функцию, которая возвращает нужные значения в виде data.frame. Для вашего использования вы, вероятно, вычислите результат timefit в функции, а затем извлечете каждое из значений в виде возвращаемого столбца:

myFunc <- function(x){
  data.frame(a= x + 1, b = x + 2, c = x + 3)
}

Затем сгруппируйте по столбцам, которые вы хотите разделить (и вернуть), и вызовите do:

myData %>%
  group_by(RT) %>%
  do((myFunc(.$RT)))

Что в данном случае возвращает это:

     RT     a     b     c
1     1     2     3     4
2     2     3     4     5
3     3     4     5     6
4     4     5     6     7
person Mark Peterson    schedule 10.10.2016