R: назначить переменные метки столбцов фрейма данных

Я борюсь с переменными метками столбцов data.frame. Скажем, у меня есть следующий фрейм данных (часть гораздо большего фрейма данных):

data <- data.frame(age = c(21, 30, 25, 41, 29, 33), sex = factor(c(1, 2, 1, 2, 1, 2), labels = c("Female", "Male")))
#

У меня также есть именованный вектор с метками переменных для этого фрейма данных:

var.labels <- c(age = "Age in Years", sex = "Sex of the participant")

Я хочу назначить метки переменных в var.labels столбцам в фрейме данных data, используя функцию label из пакета Hmisc. Я могу делать их по очереди вот так, а потом проверять результат:

> label(data[["age"]]) <- "Age in years"
> label(data[["sex"]]) <- "Sex of the participant"
> label(data)
                 age                      sex
      "Age in years" "Sex of the participant"

Метки переменных назначаются как атрибуты столбцов:

> attr(data[["age"]], "label")
[1] "Age in years"
> attr(data[["sex"]], "label")
[1] "Sex of the participant"

Чудесно. Однако с большим фреймом данных, скажем, 100 или более столбцов, это не будет удобно или эффективно. Другой вариант - назначить их напрямую как атрибуты:

> attr(data, "variable.labels") <- var.labels

Не помогает. Ярлыки переменных столбцам не присваиваются:

> label(data)
age sex
 ""  ""

Вместо этого они назначаются как атрибут самого фрейма данных (см. Последний компонент списка):

> attributes(data)
$names
[1] "age" "sex"

$row.names
[1] 1 2 3 4 5 6

$class
[1] "data.frame"

$variable.labels
                 age                      sex
      "Age in Years" "Sex of the participant"

И я не этого хочу. Мне нужны метки переменных как атрибуты столбцов. Я попытался написать следующую функцию (и многие другие):

set.var.labels <- function(dataframe, label.vector){
  column.names <- names(dataframe)
  dataframe <- mapply(label, column.names, label.vector)
  return(dataframe)
}

А затем выполните:

> set.var.labels(data, var.labels)

Не помогло. Он возвращает значения вектора var.labels, но не назначает метки переменных. Если я попытаюсь назначить его новому объекту, он просто содержит значения меток переменных в виде вектора.


person panman    schedule 07.12.2014    source источник


Ответы (4)


Вы можете сделать это, создав список из именованного вектора var.labels и назначив его значениям label. Я использовал match, чтобы гарантировать, что значения var.labels присваиваются соответствующему столбцу в data, даже если порядок var.labels отличается от порядка data столбцов.

library(Hmisc)

var.labels = c(age="Age in Years", sex="Sex of the participant")

label(data) = as.list(var.labels[match(names(data), names(var.labels))])

label(data)
                     age                      sex 
          "Age in Years" "Sex of the participant" 

Исходный ответ

В моем первоначальном ответе использовалось lapply, что на самом деле не нужно. Вот исходный ответ для архивных целей:

Вы можете назначить метки, используя lapply:

label(data) = lapply(names(data), function(x) var.labels[match(x, names(var.labels))])

lapply применяет функцию к каждому элементу списка или вектора. В этом случае функция применяется к каждому значению names(data) и выбирает значение метки из var.labels, которое соответствует текущему значению names(data).

Чтение нескольких руководств - хороший способ получить общее представление, но вы действительно освоите его, если начнете использовать lapply в разных ситуациях и посмотрите, как он себя ведет.

person eipi10    schedule 07.12.2014
comment
@ eipi10: Большое спасибо! Оно работает! Это ТОЧНО то, что мне было нужно. У меня проблемы с пониманием индексации при работе с семейством функций apply. Есть ли какое-нибудь руководство, которое я мог бы прочитать, или это вопрос опыта? - person panman; 08.12.2014
comment
Краткие руководства по lapply, this и это может быть полезным. Я также добавил еще несколько пояснений к своему ответу. - person eipi10; 08.12.2014
comment
Спасибо! Я не понимаю, почему после того, как вы сделаете lapply(names(var.labels), function(x) label(data[,x]) = var.labels[x]), где уже есть присвоение метки, нужно сделать label(data) = - person iago; 11.05.2018
comment
Ты прав. Нет необходимости выполнять задание. Спасибо что подметил это. Я исправил код, а также обновил код, чтобы он присваивал правильные метки независимо от порядка var.labels и независимо от того, включает ли names(var.labels) дополнительные элементы, которых нет в names(data). - person eipi10; 12.05.2018
comment
Собственно, возвращаясь к этому через несколько лет, я вижу, что lapply даже не понадобилось. Я обновил ответ соответственно. Однако ответ @avallecam с использованием Hmisc функции upData - более удобный способ обновления меток. - person eipi10; 12.05.2018

Я настоятельно рекомендую использовать функцию Hmisc::upData().

Вот пример REPEX:


set.seed(22)
data <- data.frame(age = floor(rnorm(6,25,10)), 
                   sex = gl(2,1,6, labels = c("f","m")))
var.labels <- c(age = "Age in Years", 
                sex = "Sex of the participant")
dplyr::as.tbl(data) # as tibble ---------------------------------------------
#> # A tibble: 6 × 2
#>     age    sex
#>   <dbl> <fctr>
#> 1    19      f
#> 2    49      m
#> 3    35      f
#> 4    27      m
#> 5    22      f
#> 6    43      m
data <- Hmisc::upData(data, labels = var.labels) # update data --------------
#> Input object size:    1328 bytes;     2 variables     6 observations
#> New object size: 2096 bytes; 2 variables 6 observations
Hmisc::label(data) # check new labels ---------------------------------------
#>                      age                      sex 
#>           "Age in Years" "Sex of the participant"
Hmisc::contents(data) # data dictionary -------------------------------------
#> 
#> Data frame:data  6 observations and 2 variables    Maximum # NAs:0
#> 
#> 
#>                     Labels Levels   Class Storage
#> age           Age in Years        integer integer
#> sex Sex of the participant      2         integer
#> 
#> +--------+------+
#> |Variable|Levels|
#> +--------+------+
#> |   sex  |  f,m |
#> +--------+------+
person avallecam    schedule 11.04.2017
comment
Hmisc::upData(data, labels = ) потрясающе! Ищу это часами. - person בנימן הגלילי; 08.08.2017
comment
Если вы хотите экспортировать метки переменных в формат .dta (stata), Hmisc::upData() показывает это проблема. Вместо этого используйте labelled::set_variable_labels(), например: cars %>% labelled::set_variable_labels(speed = "speed in mph", dist = "stopping distance in ft") %>% haven::write_dta("cars.dta") - person avallecam; 20.08.2018

Вместо {Hmisc} можно использовать пакет {labelled}:

data <- labelled::set_variable_labels(data, .labels = var.labels)
person Vlad    schedule 31.07.2020
comment
Может быть, глупый вопрос, но R-скрипт не поддерживает метки переменных из коробки? То есть вам всегда нужен дополнительный пакет с функциями для добавления или изменения меток? - person BdR; 09.04.2021
comment
Вы можете использовать базовую функцию R attr(). См. Главный вопрос. Опора на пакеты объясняется тем, что назначать атрибуты не очень удобно. Проблема в том, что базовый R делает это в очень общем виде, а не специально нацелен на задачу простой маркировки переменных или значений. - person Vlad; 10.04.2021

Если ваш вектор меток соответствует порядку столбцов data.frame, но не является именованным вектором (поэтому его нельзя использовать для подмножества столбцов data.frame по имени, как подход lapply в другом ответе), вы можете использовать цикл for:

for(i in seq_along(data)){
  Hmisc::label(data[, i]) <- var.labels[i]
}

label(data)
#>                      age                      sex 
#>           "Age in Years" "Sex of the participant"
person Sam Firke    schedule 30.03.2017