возможно ли в R использовать имя входного кадра данных в самодельной функции, которая создает кадры данных?

#r #dataframe #function

Вопрос:

У меня есть рабочая функция, которая составляет около 250 строк, упрощенная версия:

 myfunction lt;- function(x){    WithoutNA lt;lt;- x[!(is.na(x$Height)),]  Heavy lt;- WithoutNA[WithoutNA$Weight gt;= "150",]  Light lt;- WithoutNA[WithoutNA$Weight lt; "150",]   HL lt;lt;- Heavy[Heavy$FurColor=="light_Brown",]  HD lt;lt;- Heavy[Heavy$FurColor=="Dark_Brown",]   LL lt;lt;- Light[Leavy$FurColor=="light_Brown",]  LD lt;lt;- Light[Leavy$FurColor=="Dark_Brown",] }  

Таким образом, эта функция даст 4 разных кадра данных, исключая строки, в которых отсутствует высота, разделенные по весу и цвету меха .Проблема, с которой я сталкиваюсь, заключается в том, что если я использую эту функцию на двух разных кадрах данных во второй раз, она, конечно, переопределит 4 кадра данных, которые она создала при первом использовании функции.

если я введу:

 myfunction(Horse) myfunction(Pony)  

Мне бы хотелось, чтобы 8 кадров данных назывались: HL_Horse, HD_Horse, LL_Horse, LD_Horse, HL_Pony, HD_Pony, LL_Pony и LD_Pony

Но я, похоже, не могу понять, как вставить имя фрейма данных в мои недавно созданные имена фреймов данных. Возможно ли вообще создать имя фрейма данных «переменная»?

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

1. fortunes::fortune(174)

2. Как намекает @jogo, вся эта концепция ошибочна. R-это (в основном) функциональный язык программирования, и пользователи не ожидают побочных эффектов, особенно (чрезмерной)записи объектов в вызывающей среде. Гораздо лучшая идея состоит в том, чтобы ваша функция возвращала список фреймов данных. Списки лучше по ряду причин. Они не загромождают глобальную рабочую область, их можно повторять, им можно давать имена, они могут быть вложены, их можно преобразовать в среды, и они могут действовать как контейнер, позволяющий функции возвращать несколько объектов — как в вашем примере.

3. (Для тех, кто не fortunes установлен: «Я хотел бы lt; Если вы хотите перевести R/S на макроязык, этот оператор для вас. — Билл Венейблс, R-help (июль 2001)» )

4. @Аллан Камерон, я должен согласиться, что моя среда в данный момент беспорядочная, используя мою функцию только один раз, список действительно решил бы эту проблему. Но разве это не означает, что если я выполню функцию 30 раз, то в итоге получу 30 списков, содержащих все объекты с одинаковыми именами?

5. @Omniswitcher да, но название каждого списка разное, поэтому легко получить доступ к каждому отдельному фрейму данных (см. Мой ответ в качестве примера). Вы даже можете объединить все 30 списков в один основной список, чтобы в вашей глобальной среде был один объект.

Ответ №1:

Вся эта концепция ошибочна. R-это (в основном) функциональный язык программирования, и пользователи не ожидают побочных эффектов, особенно (чрезмерной)записи объектов в вызывающей среде. Гораздо лучшая идея состоит в том, чтобы ваша функция возвращала список фреймов данных.

Списки лучше, чем прямая запись в вызывающую среду по ряду причин. Они не загромождают глобальную рабочую область, их можно повторять, их элементы могут быть именованными или безымянными, они могут быть вложенными, их можно преобразовать в среды и они могут действовать как контейнер, позволяющий функции возвращать несколько объектов — как в вашем примере.

Стандартный способ R использовать функцию, подобную вашей, был бы примерно таким:

 myfunction lt;- function(x){    WithoutNA lt;- x[!(is.na(x$Height)),]  Heavy lt;- WithoutNA[WithoutNA$Weight gt;= "150",]  Light lt;- WithoutNA[WithoutNA$Weight lt; "150",]    HL lt;- Heavy[Heavy$FurColor=="light_Brown",]  HD lt;- Heavy[Heavy$FurColor=="Dark_Brown",]    LL lt;- Light[Light$FurColor=="light_Brown",]  LD lt;- Light[Light$FurColor=="Dark_Brown",]    return(list(HL = HL, HD = HD, LL = LL, LD = LD)) }  

Теперь, если мы дадим ему немного игрушечных данных:

 df lt;- data.frame(Height = c(2, 2, 2, 2),  Weight = c(100, 100, 200, 200),  FurColor = rep(c("light_Brown", "Dark_Brown"), 2))  horse lt;- myfunction(df) pony lt;- myfunction(df)  

Мы можем легко получить доступ к каждому из 8 фреймов данных, например, выполнив:

 horse$HL #gt; Height Weight FurColor #gt; 3 2 200 light_Brown  pony$LD #gt; Height Weight FurColor #gt; 2 2 100 Dark_Brown  

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

Если вы хотите сделать свое глобальное рабочее пространство еще менее загроможденным, вы даже можете разместить списки так, чтобы все ваши фреймы данных находились в одном главном списке. Так, например, вы могли бы:

 equines lt;- list() equines$horse lt;- myfunction(df) equines$pony lt;- myfunction(df)  

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

 equines$pony$HL #gt; Height Weight FurColor #gt; 3 2 200 light_Brown  

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

1. Большое спасибо! Я уже использую ‘ Я могу поддерживать более чистую среду с логическим доступом ко всему, что мне нужно.