foreach并行化与tibble之间的数据结构兼容性问题

foreach并行化与tibble之间的数据结构兼容性问题,r,dataframe,tibble,parallel-foreach,R,Dataframe,Tibble,Parallel Foreach,我发现,当使用classdata.frame对象时,函数pec::predictSurvProb在foreach循环中运行良好,但当使用classtbl_df对象时,该函数不起作用,而classtbl_df对象似乎是使用dplyr操作时生成的默认tibble类。我收到一条没有多大帮助的错误消息:{strong>中出现错误: 任务1失败-“与请求的类型不兼容:[type=list;target=double]。” 解决方案是将我的数据从tbl_df转换为classdata.frame,但我很好奇为

我发现,当使用class
data.frame
对象时,函数
pec::predictSurvProb
foreach
循环中运行良好,但当使用class
tbl_df
对象时,该函数不起作用,而class
tbl_df
对象似乎是使用
dplyr
操作时生成的默认
tibble
类。我收到一条没有多大帮助的错误消息:{strong>中出现错误: 任务1失败-“与请求的类型不兼容:[type=list;target=double]。”

解决方案是将我的数据从
tbl_df
转换为class
data.frame
,但我很好奇为什么会出现这个问题。看起来TIBLES实际上不是数据帧的扩展,因为它们的行为不同,并且这种行为与其他R包不兼容

我不确定这种类型的不兼容性是否有充分的记录,但我发现这里有一个简短的讨论:

我已尝试在以下
repex
中显示该问题:

# repex
library(survival)
library(pec)
library(dplyr)
library(doParallel) 

data("lung") # example data set
class(lung) # which is class data.frame

lung2 <- lung %>%
group_by(inst) %>%
mutate(T_MAX = max(time)) %>%
ungroup() # use dplyr to create a new variable T_MAX

class(lung2) # lung2 is of class tibble (tbl_df)

lung3 <- lung %>%
group_by(inst) %>%
mutate(T_MAX = max(time)) %>%
ungroup() %>%
as.data.frame() # same dplyr manipulation but coercion to class data.frame at the end

class(lung3) # lung3 is of class data.frame

# create identical Cox PH models using the different data sets lung2 and lung3
mdl_lung2 <- coxph(Surv(time, status) ~ inst + age + sex,
               data = lung2,
               x = TRUE)

summary(mdl_lung2)

mdl_lung3 <- coxph(Surv(time, status) ~ inst + age + sex,
               data = lung3,
               x = TRUE)

summary(mdl_lung3)

# predictSurvProb function works and output is the same
predictSurvProb(mdl_lung2, newdata = lung2, times = 365)
predictSurvProb(mdl_lung3, newdata = lung3, times = 365)

# initiate parallelisation
cores <- detectCores() 
registerDoParallel(cores = cores) 
cat("No. of cores initiated for parallel processing:", getDoParWorkers()) 

# foreach application does not work using lung2
lung2$P_TEST <- foreach(j=1:nrow(lung2),
                      .combine = c) %dopar% { # Return a vector
                        predictSurvProb(mdl_lung2, lung2[j, ], times = lung2[j, "T_MAX"])
                      }

# but does using lung3
lung3$P_TEST <- foreach(j=1:nrow(lung3),
                   .combine = c) %dopar% { # Return a vector
                     predictSurvProb(mdl_lung3, lung3[j, ], times = lung3[j, "T_MAX"])
                   }

summary(lung3$P_TEST)
#repex
图书馆(生存)
图书馆(pec)
图书馆(dplyr)
图书馆(双平行)
数据(“肺”)#示例数据集
class(lung)#这是class data.frame
肺2%
分组人(仪表)%>%
变异(T_MAX=MAX(time))%>%
解组()#使用dplyr创建新变量T_MAX
等级(lung2)#lung2属于TIBLE等级(待定)
肺3%
分组人(仪表)%>%
变异(T_MAX=MAX(time))%>%
解组()%>%
as.data.frame()#与dplyr操作相同,但最后强制类data.frame
类(lung3)#lung3属于类data.frame
#使用不同的数据集lung2和lung3创建相同的Cox PH模型

mdl_lung2在没有查看软件包代码的情况下,我会说您正确地诊断了问题,并且软件包依赖于特定的
数据。大多数人都认为frame
行为是错误的。因此,最好的做法是,如果软件包作者修复了软件包,使其不依赖于该行为。作为副作用,我然后t也会使用TIBLES(严格来说,这会破坏
data.frame
-的继承契约,但有一个很好的理由)。这与
foreach
无关。比较
lung2[1,“t_MAX”]
lung3[1,“t_MAX”]
。问题在于
[.data.frame
[.tbl_df
@KonradRudolph这不是软件包问题,而是用户错误。顺便说一句。只需使用
%do%
而不是
%dopar%
,您就会看到一条信息性错误消息。@Roland哦,的确如此。@Seanospien它在循环之外工作,因为在循环之外,您没有对
lungX
数据集进行子集设置,您正在传入g将他们全部添加到
coxph
中。在没有查看包代码的情况下,我会说您正确地诊断了问题,并且包依赖于特定的
数据。大多数人都认为框架
行为是错误的。因此,如果包作者将包修复为不依赖于作为一种副作用,它也会与tibbles一起工作(严格来说,这会破坏
data.frame
-的继承契约,但有一个很好的理由)。这与
foreach
无关。比较
lung2[1,“T_MAX”]
lung3[1,“T_MAX”]
。问题在于
[.data.frame
[.tbl_df
@KonradRudolph这不是软件包问题,而是用户错误。顺便说一句。只需使用
%do%
而不是
%dopar%
,您就会看到一条信息性错误消息。@Roland哦,的确如此。@Seanospien它在循环之外工作,因为在循环之外,您没有对
lungX
数据集进行子集设置,您正在传入将它们全部添加到
coxph