Есть ли более эффективный способ создать data.frame, содержащий описания каждой переменной в R?

#r #dataframe #vector #metadata #mode

#r #dataframe #вектор #метаданные #режим

Вопрос:

У меня есть data.frame в R (давайте в качестве примера используем встроенный набор данных «mtcars»), и я хотел бы найти более эффективный способ создания второго data.frame, содержащего описания каждой переменной (т. Е. Некоторые Базовые метаданные) следующим образом:

 Variables    Type                                   Labels
      mpg numeric                        Miles/(US) gallon
      cyl numeric                      Number of cylinders
     disp numeric                    Displacement (cu.in.)
       hp numeric                         Gross horsepower
     drat numeric                          Rear axle ratio
       wt numeric                        Weight (1000 lbs)
     qsec numeric                            1/4 mile time
       vs numeric      Engine (0 = V-shaped, 1 = straight)
       am numeric Transmission (0 = automatic, 1 = manual)
     gear numeric                  Number of forward gears
     carb numeric                    Number of carburetors
  

Приведенный ниже код указывает мой текущий метод получения data.frame с описаниями каждой переменной, включая имена переменных, типы переменных элементов и метки.

 dat01 <- mtcars

Variables <- c(names(dat01))

#install.packages("Hmisc")
library(Hmisc)
var.labels = c(mpg="Miles/(US) gallon",
               cyl="Number of cylinders",
               disp="Displacement (cu.in.)",
               hp="Gross horsepower",
               drat="Rear axle ratio",
               wt="Weight (1000 lbs)",
               qsec="1/4 mile time",
               vs="Engine (0 = V-shaped, 1 = straight)",
               am="Transmission (0 = automatic, 1 = manual)",
               gear="Number of forward gears",
               carb="Number of carburetors")

label(dat01) <- as.list(var.labels[match(names(dat01), names(var.labels))])

Labels <- label(dat01)

Type <- c(mode(dat01$mpg),
          mode(dat01$cyl),
          mode(dat01$disp),
          mode(dat01$hp),
          mode(dat01$drat),
          mode(dat01$wt),
          mode(dat01$qsec),
          mode(dat01$vs),
          mode(dat01$am),
          mode(dat01$gear),
          mode(dat01$carb))

meta.df <- data.frame(Variables,
                      Type,
                      Labels)

print(meta.df, row.names = FALSE)
  

В дополнение к повышению эффективности моего скрипта (в частности, я уверен, что существует более эффективный код, который я могу использовать для создания векторного «Типа»), мне также интересно услышать ваши предложения о том, как лучше обобщить этот скрипт, чтобы его можно было копировать / вставлять и применять каналогично структурированные data.frames.

Комментарии:

1. Type = sapply(mtcars, mode) было бы довольно стандартным. Способ сделать его обобщаемым — поместить его в функцию, возможно, функцию данных, принимая пользовательские метки в качестве необязательного аргумента.

2. Я бы также задался вопросом, уверены ли вы mode , что это нужная вам информация. class это намного полезнее, но тогда вам нужно решить, что делать с многоклассовыми объектами. Но такие вещи, как mode(factor(1:3)) , mode(Sys.Date()) , mode(Sys.time()) — это все numeric , что заставляет меня не любить mode .

3. Я не уверен, что вы имеете в виду, когда говорите, что режим является числовым. Когда я использую mode (variable.name ), он возвращает символьную строку, указывающую тип элемента данных (например, «символьный», «числовой», «логический» и т.д.). Кажется, что класс (variable.name ) делает то же самое, за исключением того, что sapply(dat01, class) также возвращает строку, указывающую, что каждый столбец в моем фрейме данных «помечен».

4. Да, mode и class возвращать символьные строки. mode(Sys.Date()) возвращает символьную строку "numeric" , поскольку даты хранятся внутри в виде чисел. class(Sys.Date()) возвращает символьную строку "Date" . Я хочу сказать, что class возвращаемая информация более полезна, поскольку факторы, даты, временные метки и целые числа будут идентифицироваться mode как простые "numeric" , но class будут различать их и обычные цифры. Информация, возвращаемая class обычно, более полезна.

5. test_list = list(date = Sys.Date(), time = Sys.time(), factor = factor('a'), integer = 1L, numeric = 1.5) . Сравните lapply(test_list, mode) с lapply(test_list, class) . Но здесь вы также можете видеть, что class необязательно возвращать строки длиной 1, class(Sys.time()) , class(factor('a', ordered = T)) — это два базовых примера с несколькими классами… что может усложнить задачу. Выбор class(x)[1] был бы довольно хорошим значением по умолчанию.

Ответ №1:

Первым решением было бы дедуплицировать это Type определение:

Поскольку class(some_vector) возвращает единственную строку, описывающую тип данных в этом векторе, и поскольку фрейм данных представляет собой список векторов, вы можете использовать такой код:

 Type <- unlist(Map(class, mtcars))
  

[однако вам может потребоваться изменить порядок записей]

Комментарии:

1. class не всегда возвращает одну строку. Попробуйте class(factor(1:3, ordered = TRUE)) или class(Sys.time()) для примеров многоклассовых объектов, которые часто отображаются в виде столбцов данных.

2. прошу прощения, моя ошибка