Как добавить метаданные в тиббл

Как добавить метаданные в тиббл?

Мне нужно предложение, описывающее каждое из моих имен переменных, чтобы я мог распечатать тибл со связанными метаданными, и если бы я передал его кому-то, кто раньше не видел данных, они могли бы понять это.

as_tibble(iris)

# A tibble: 150 × 5
   Sepal.Length Sepal.Width Petal.Length Petal.Width Species
          <dbl>       <dbl>        <dbl>       <dbl>  <fctr>
1           5.1         3.5          1.4         0.2  setosa
2           4.9         3.0          1.4         0.2  setosa
3           4.7         3.2          1.3         0.2  setosa
4           4.6         3.1          1.5         0.2  setosa
5           5.0         3.6          1.4         0.2  setosa
6           5.4         3.9          1.7         0.4  setosa
7           4.6         3.4          1.4         0.3  setosa
8           5.0         3.4          1.5         0.2  setosa
9           4.4         2.9          1.4         0.2  setosa
10          4.9         3.1          1.5         0.1  setosa
# ... with 140 more rows

# Sepal.length. Measured from sepal attachment to stem
# Sepal.width. Measured at the widest point
# Petal.length. Measured from petal attachment to stem
# Petal.width. Measured at widest point
# Species. Nomenclature based on Integrated Taxonomic Information System (ITIS), January 2018.

Благодарность!


person Adrienne B    schedule 08.01.2018    source источник
comment
?comment скорее всего будет тем, что вы ищете   -  person hrbrmstr    schedule 08.01.2018


Ответы (2)


Это кажется сложным. В принципе, можно использовать комментарий @ hrbrmstr (т.е. используйте ?comment или ?attr для добавления атрибутов к любому объекту), но эти атрибуты не будут распечатаны по умолчанию. Атрибуты кажутся автоматически печатаемыми для атомарных объектов:

> z <- 1:6
> attr(z,"hello") <- "goodbye"
> z
[1] 1 2 3 4 5 6
attr(,"hello")
[1] "goodbye"

... но, увы, не для фреймов данных или таблиц:

dd <- tibble::data_frame(x=1:4,y=2:5)
> attr(dd,"metadata") <- c("some stuff","some more stuff")
> dd
# A tibble: 4 x 2
      x     y
  <int> <int>
1     1     2
2     2     3
3     3     4
4     4     5

Вы можете обернуть объект его собственным классом S3, чтобы напечатать этот материал:

class(dd) <- c("my_tbl",class(dd))
> print.my_tbl <- function(x) {
+    NextMethod(x)
+    print(attr(x,"metadata"))
+    invisible(x)
+ }
> dd
# A tibble: 4 x 2
      x     y
  <int> <int>
1     1     2
2     2     3
3     3     4
4     4     5
[1] "some stuff"      "some more stuff"

Вы можете сделать печать более сложной или красивой, например

cat("\nMETADATA:\n")
cat(sprintf("# %s",attr(x,"metadata")),sep="\n")

Ничего плохого не произойдет, если другой пользователь не определил print.my_tbl (метод печати вернется к методу печати для таблиц), но метаданные будут напечатаны только в том случае, если они имеют ваше print.my_tbl определение ...

person Ben Bolker    schedule 08.01.2018
comment
Бен очень помогает. Есть ли способ сделать что-то подобное, но только распечатать атрибуты во время загрузки таблицы из файла RDS? - person jzadra; 27.08.2020
comment
это действительно кажется очень сложным. Методу печати для объекта трудно узнать, был ли объект загружен только что или какое-то время находился в сеансе. Самый простой способ, который я могу придумать, - это (1) добавить print_attributes в качестве аргумента к print.my_tbl (со значением по умолчанию FALSE); (2) напишите специальную функцию read_my_tbl(), которая вызывает x <- readRDS(...) и print(x, print_attributes=TRUE), а затем возвращает invisible(x) (чтобы объект больше не печатался. - person Ben Bolker; 27.08.2020
comment
Спасибо, Бен. У меня была такая же мысль, и в настоящее время я использую пользовательскую функцию чтения. Рад знать, что по крайней мере нет более простого решения! - person jzadra; 27.08.2020

Это не так уж и отличается от предложений Бена Болкера, но концептуально, если я хочу, чтобы информация была связана с векторами в моем фрейме данных, я бы предпочел, чтобы они были напрямую связаны с векторами. Другими словами, я бы предпочел добавлять атрибуты к самим векторам, а не к объекту фрейма данных.

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

library(tibble)
library(ggplot2)
library(magrittr)
library(labelVector)

print_with_label <- function(dframe){
  stopifnot(inherits(dframe, "data.frame"))
  labs <- labelVector::get_label(dframe, names(dframe))
  labs <- sprintf("%s: %s", names(dframe), labs)
  print(dframe)
  cat("\n")
  cat(labs, sep = "\n")
}

iris <- 
  as_tibble(iris) %>%  
  set_label(Sepal.Length = "This is a user friendly label",
            Petal.Length = "I much prefer reading human over computer")

print_with_label(iris)

mtcars <-
  set_label(mtcars,
            mpg = "Miles per Gallon",
            qsec = "Quarter mile time",
            hp = "Horsepower",
            cyl = "Cylinders",
            disp = "Engine displacement")

print_with_label(mtcars)
person Benjamin    schedule 08.01.2018