动态分配数据框的变量以在 R 中添加值标签,使用因子,set_labels of "sjmisc" package

Dynamic assignment to variables of a dataframe for adding value labels in R, use of factors, set_labels of "sjmisc" package

我想为数字数据分配值标签,以便在我制表或生成一些图表时显示标签。牢记这一点,我想到了使用因子,以便我可以分配标签,并在需要时使用级别中的数值生成一些统计数据,例如平均值。我的数据库有 150 多个变量,我需要为其中大约 120 个变量分配值标签。变量到变量到值标签会有所不同,对于少数变量可能相同。

为了说明问题并为执行做准备,我创建了一个示例数据,如下所示 -

Q1 <- sample(1:5,20,replace = T)
Q2 <- sample(1:5,20,replace = T)
Q3 <- sample(1:5,20,replace = T)
Q4 <- sample(1:5,20,replace = T)
Q5 <- sample(1:5,20,replace = T)

df <- as.data.frame(cbind(Q1,Q2,Q3,Q4,Q5))
class(df)

我有一个单独的数据框,其中包含每个问题的值和标签

mylabel <- data.frame(Q1 = 1:5,Q1_desc = c("Strongly Disagree","Disagree","Neither","Agree","Strongly Agree"),
                  Q2 = 1:5,Q2_desc = c("Strongly Disagree","Disagree","Neither","Agree","Strongly Agree"),
                  Q3 = 1:5,Q3_desc = c("Strongly Disagree","Disagree","Neither","Agree","Strongly Agree"),
                  Q4 = 1:5,Q4_desc = c("Strongly Disagree","Disagree","Neither","Agree","Strongly Agree"),
                  Q5 = 1:5,Q5_desc = c("Strongly Disagree","Disagree","Neither","Agree","Strongly Agree"))

现在让我来说明一个变量的代码-

df$Q1 <- factor(df$Q1,
              levels = c(1,2,3,4,5),
              labels = c("Strongly Disagree","Disagree","Neither","Agree","Strongly Agree"))

df$Q1
mean(as.numeric(df$Q1))
barplot(table(df$Q1))
table(df$Q1)

以上代码将 Q1 作为一个因子,并将水平和标签分配给数据框中的 Q1 变量。我能够生成带有标签的均值/条形图和带有标签的 table 。由于我有很多变量需要执行此任务,所以我想到了编写一个函数。这就是我需要帮助的地方!

下面是函数的代码-

getlabels <- function(varname){
  #varname <- "Q1"
  lev <- na.omit(with(mylabel, get(varname)))
  lab <- na.omit(with(mylabel,get(paste0(varname,"_desc"))))
  df$varname <- factor(with(df,get(varname)),
                     levels = lev,
                     labels = lab)
}

getlabels("Q2")

上面的代码没有给出任何错误,但没有用标签和 Q2 的水平更新 df。 Q2 仍然是一个数字列。似乎因子函数的分配没有发生在 df$varname 上。有人可以建议为什么会发生这种情况以及我们如何克服这种情况。

#

然后我尝试了不同的方法,使用 "sjmisc" 包来实现这个。我可以通过以下代码为单个变量实现它 -

df$Q2 <- set_labels(df$Q2,c("Strongly Disagree","Disagree","Neither","Agree","Strongly Agree"))
df$Q2

以上将标签指定为属性。现在,因为我需要对多个变量执行此操作,所以我想到将其转换为一个函数。同样在这种情况下也无法更新 df,因为分配没有发生。 通过使用赋值函数,我没有得到任何错误,但属性没有得到更新。

getlabels2 <- function(varname){
  #varname <- "Q1"
  lev <- na.omit(with(mylabel, get(varname)))
  lab <- na.omit(with(mylabel,get(paste0(varname,"_desc"))))
  ##setting lab to named variable as set_labels needs a named variable
  names(lab) <- na.omit(paste("mylabel$","varname"))
  assign(paste("df$",varname),set_labels(with(df,varname),lab))
}

getlabels2("Q2")

df$Q2

由于变量的数量更多,我相信解决该函数将有助于自动化这一重复性任务。最后我想在 lapply 中使用该函数,这样我就不必调用该函数 120 次了。如果有人也可以对此提出建议,那将会有所帮助。

谢谢!!

我有点想知道你为什么不写一个 for 循环然后继续:

for (i in names(df)){
  df[[i]] <- factor(df[[i]],
                    levels = mylabel[[i]],
                    labels = mylabel[[paste0(i,"_desc")]])
}

> str(df)
'data.frame':   20 obs. of  5 variables:
 $ Q1: Factor w/ 5 levels "Strongly Disagree",..: 2 2 4 1 4 2 5 5 1 2 ...
 $ Q2: Factor w/ 5 levels "Strongly Disagree",..: 1 5 3 3 2 3 5 1 4 2 ...
 $ Q3: Factor w/ 5 levels "Strongly Disagree",..: 2 5 2 5 5 2 4 4 5 3 ...
 $ Q4: Factor w/ 5 levels "Strongly Disagree",..: 3 3 2 1 1 3 1 2 1 3 ...
 $ Q5: Factor w/ 5 levels "Strongly Disagree",..: 2 2 1 4 5 4 1 3 1 1 ...

附带说明一下,最好避免 as.data.frame(cbind());这是一个糟糕的代码模式,坦率地说,只是输入的次数超出了您的需要。 df <- data.frame(Q1,Q2,Q3,Q4,Q5) 足够了,也更安全。