【问题标题】:for loop with function that writes to 3 separate columns R or dplyr/reshape solution?具有写入 3 个单独列 R 或 dplyr/reshape 解决方案的函数的 for 循环?
【发布时间】:2023-09-08 14:19:01
【问题描述】:

我是 for 循环的初学者,所以如果这个问题已经有了明确的答案,我深表歉意,但我找不到任何我理解如何应用于这个特定问题的东西。最后我也开始尝试 dplyr 实现,但也无法弄清楚。

这是我的问题:有一个函数可以从向量中导出 3 个值。我想将这 3 个值写入与新列相同的 df 。该函数是来自 R 中 retimes 库的 timefit。 如果我在整个 df 上运行它:

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

如果我将值放入 df df &lt;- data.frame(a1@par):

      a1.par
mu    480.33462
sigma 77.85305
tau   376.74257

我想根据另一个变量“位置”(具有两个级别的因素)为每个子 ID 单独运行它。所以我最终得到了类似的东西

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)
}

但我知道这实际上并不能满足我的需要。值是从带有@par 的 timefit 模型中提取的长格式,所以我需要指定函数 timefit 以写入 3 个单独的列标题?有什么建议么?

另外,我考虑过使用 ddply,但最后一行让我很困惑,因为格式很长,但我需要它很宽。我对 reshape 有点搞砸了,但我很难弄清楚

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

感谢您的帮助!

【问题讨论】:

    标签: r dplyr reshape reshape2


    【解决方案1】:

    您可以在此处使用summarise 而不是mutate 生成一个列表列,其中包含来自每个(subID, location)timefitdata.frame。这些数据帧将timefit 的结果中的musigmatau 编码为列。然后,使用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()
    

    请注意,我们从timefit 类中提取"par" 属性,然后将其与t 转置以形成musigmatau 的列。

    在这里,我们假设您的输入 data 是一个数据框,其中包含 subIDlocation 列和输入到 timefit 的反应时间数字列 RT。此类数据集的模拟示例如下:

    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 生成的,因此它们介于01 之间。你的价值观有很大不同,但这在这里应该无关紧要。

    使用这些数据,我们得到:

    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
    

    【讨论】:

    • 太好了,谢谢。还想补充一下,summary 对我来说被屏蔽了(不知道为什么),但如果我没有指定 dplyr::summarise 只返回整行。
    • @MikaelRubin:这可能是因为plyr,正如您提到的您正在使用ddply。你可以detachplyrdplyr,然后加载dplyr。如果您确实需要这两个包,请确保先加载plyr,然后再加载dplyr
    【解决方案2】:

    如果您正在寻找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
    

    【讨论】:

      最近更新 更多