我有一个从 XLSX 文件中读取的数据框。每个列名看起来像这样: CODE___DESCRIPTION 例如A1___Some funky column here。将代码用作列名更容易,但我想在需要时使用描述,因此它必须存储在数据框中。这就是我稍后使用sjlabelled包的原因。
为自己制作一些随机数据并将其保存为some_data.xlsx。
library(dplyr) #to play with tibbles
library(stringi) #to play with strings
library(writexl) #name speaks for itself
tibble(col1 = sample(c("a", "b", "c", NA, "N/A"), 50, replace = T),
col2 = sample(c("d", "e", "f", NA, "N/A"), 50, replace = T),
col3 = sample(c("g", "h", "i", NA, "N/A"), 50, replace = T),
col4 = sample(c("j", "k", "l", NA, "N/A"), 50, replace = T)) %>%
setNames(stri_c("A", 1:4, "___", stri_rand_strings(4, 10))) %>%
write_xlsx(path = "some_data.xlsx", col_names = T, format_headers = F)
我创建了简单的函数来按照我想要的方式准备我的数据。
library(sjlabelled) #to play with labelled data
label_it <- function(data = NULL, split = "___"){
#This basically makes an array of two columns (of codes and descriptions respectively)
k.n <- data %>%
names() %>%
stri_split_fixed(pattern = split, simplify = T)
data%>%
set_label(k.n[,2]) %>% #set description as each column's label
setNames(k.n[,1]) #set code as each column's name
}
首先我从 XLSX 文件中读取数据。然后我给它贴上标签。
library(readxl) #name speaks for itself again
data <- read_xlsx("some_data.xlsx", na = c("", "N/A")) %>%
label_it()
现在我的每个数据框的列都是具有两个属性的字符向量(实际上它是一个结构):
- 标签是描述部分
- 名称是原始数据框列名称(CODE___DESCRIPTION 样式),不要误认为名称(数据)的输出,这将是代码部分
假设我想将第一列和第三列更改为因子。
为此,我尝试了两件事:
data[,1] <- factor(data[,1], levels = c("c", "a", "b"))
data[,3] <- factor(data[,3], levels = c("h", "g", "i"))
这会将所有这两个列的值更改为 NA_integer_。
data <- data %>%
mutate(A1 = factor(A1, levels = c("c", "a", "b")),
A3 = factor(A3, levels = c("h", "g", "i")))
这会将字符向量更改为预期的因子,但它会删除我需要保留的两个列属性(标签和名称)。
我还尝试了sjlabelled、labeled和Have包中的很多功能。没有按我的预期工作。最后,我找到了一个解决方案,但它并不完美,我很想找到一种更简单的方法来做到这一点。
解决方案是失去这些属性,然后重新获得(实际上是“复制”)它们。
data <- data %>%
mutate(A1 = factor(A1, levels = c("c", "a", "b")),
A3 = factor(A3, levels = c("h", "g", "i"))) %>%
copy_labels(data)
copy_labels
是来自sjlabelled包的函数,当标签由于例如数据子集而丢失时使用,如本例所示。
PS 我很想添加r-sjlabelled和r-labelled标签,因为在这个问题中考虑了这些包,但执行此操作所需的声誉低于 1500。