Как изменить функцию melt.data.frame в пакете reshape2, возвращенный столбец "variable" в класс "character"?

Поведение melt.data.frame по умолчанию заключается в возврате столбца "variable" в классе "factor". Вот пример:

> head(airquality)

  ozone solar.r wind temp month day
1    41     190  7.4   67     5   1
2    36     118  8.0   72     5   2
3    12     149 12.6   74     5   3
4    18     313 11.5   62     5   4
5    NA      NA 14.3   56     5   5
6    28      NA 14.9   66     5   6

> x = melt(head(airquality))
Using  as id variables

> head(x)
  variable value
1    ozone    41
2    ozone    36
3    ozone    12
4    ozone    18
5    ozone    NA
6    ozone    28

> class(x$variable)
[1] "factor"

Вопрос в том, есть ли какой-либо параметр для изменения класса от фактора к символу? Я пробовал options(stringsAsFactors = FALSE), но он не работает.

Ответ 1

Я не верю, что есть такой вариант, встроенный в melt.data.frame. Однако, если вы проверите код, изменить его не сложно. Мы можем определить новую функцию melt.df, которая заменяет соответствующую строку быстрой проверкой, чтобы определить, установлен ли пользователь stringsAsFactors = FALSE:

if (getOption("stringsAsFactors")){
    df[[variable_name]] <- factor(df[[variable_name]], 
                                   unique(df[[variable_name]]))
}
else{
   df[[variable_name]] <- as.character(factor(df[[variable_name]],         
                                   unique(df[[variable_name]])))
}

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

Ответ 2

Когда большинство пользователей переходят к "tidyverse" или "data.table" для изменения данных в эти дни, ваши варианты улучшились.

В "tidyverse" поведение по умолчанию заключается в том, чтобы сохранить переменную расплавленного как character s:

library(tidyverse)
airquality %>% gather(var, val, everything()) %>% str()
# 'data.frame': 918 obs. of  2 variables:
#  $ var: chr  "Ozone" "Ozone" "Ozone" "Ozone" ...
#  $ val: num  41 36 12 18 NA 28 23 19 8 NA ...

В реализации "data.table" melt добавлено несколько новых аргументов, один из которых - variable.factor, который может быть установлен на FALSE. Я полагаю, что он установлен на TRUE по согласованию с реализацией "reshape2" melt.

library(data.table)
str(melt(as.data.table(airquality), variable.factor = FALSE))
# Classes ‘data.table’ and 'data.frame':    36 obs. of  2 variables:
#  $ variable: chr  "Ozone" "Ozone" "Ozone" "Ozone" ...
#  $ value   : num  41 36 12 18 NA 28 190 118 149 313 ...
#  - attr(*, ".internal.selfref")=<externalptr>