eval parse在我的函数中无法正常工作

时间:2017-05-30 17:08:33

标签: r function labels levels

我有以下数据集,其中包含2个变量:

dt4<-structure(list(a1 = c(4L, 4L, 3L, 4L, 4L), a2 = c(1L, 
3L, 4L, 5L, 4L)), .Names = c("a1", "a2"
), row.names = c(NA, -5L), class = c("tbl_df", "tbl", "data.frame"
))

我有以下功能可以为现有数据集添加标签和级别:

Add_Labels_Level_To_Dataset <- function(df, df_name,levels_list,labels_list)   {
  df[] <- lapply( df, ordered)
  for (i in 1:length(colnames(df))) {
    arg0<-paste0(df_name,"[i]", "<-ordered(", df_name, "$'", colnames(df)[i], "', levels=c(", levels_list[[i]], "), labels = c(", labels_list[[i]],"))"  )
    eval(parse(text=arg0))
      }
df
  }

由该R命令运行:

Add_Labels_Level_To_Dataset(dt4, "dt4", level_list, labels_list)

R命令中提供的列表分别代表数据集中每个变量的有序级别:

label_list=list("'S','SA','SB','SC,'SD'", "'S','SA','SB','SC,'SD'")
level_list=list("5,4,3,2,1", "5,4,3,2,1")

为什么我的功能无法正常工作? 我不知道那有什么问题! 当我在R函数外部运行R命令时,它们将水平/标签绑定到给定的数据集。但是,当我运行我的R功能时,这不会发生!

  df_name="dt4"
  df=dt4
  levels_list=level_list
  labels_list=label_list
  i=3

  df[] <- lapply( df, ordered)
          arg0<-paste0(df_name,"[i]", "<-ordered(", df_name, "$'", colnames(df)[i], "', levels=c(", levels_list[[i]], "), labels = c(", labels_list[[i]],"))"  )
                eval(parse(text=arg0))
你能帮忙吗?

2 个答案:

答案 0 :(得分:1)

Using eval/parse should be avoided。有更简单的方法可以在R中执行您想要的操作。例如,使用此代码,我们可以编写

Add_Labels_Level_To_Dataset <- function(df, levels_list, labels_list)   {
  df[] <- Map(function(data, levels, labels) {
     ordered(data, levels=strsplit(levels,",")[[1]], labels=strsplit(labels, ",")[[1]])
  }, df, levels_list, labels_list)
  df
}

我们可以称之为

dt4 <- Add_Labels_Level_To_Dataset(dt4, level_list, label_list)

请注意,它会返回一个新的data.frame,您可以将其重新分配给dt4或其他一些变量。 R中的函数永远不应该修改自己范围之外的对象,这是导致函数出现问题的其他原因之一。

答案 1 :(得分:1)

这是xy problem。我同意@MrFlick应该避免解析。 在原帖上,主要问题是函数应该返回dt4而不是df。定义label_list时,有一些缺少'(单引号)。

我们可以使用mapply并避免使用单引号:

label_list=list(c('S','SA','SB','SC','SD'), c('S','SA','SB','SC','SD'))
level_list=list(c(5,4,3,2,1), c(5,4,3,2,1))

as.data.frame(mapply(function(x, labels,levels ) {ordered(x, labels,levels)}, dt4, level_list, label_list, SIMPLIFY = F))
#  a1 a2
#1 SA SD
#2 SA SB
#3 SB SA
#4 SA  S
#5 SA SA