Почему rbind не работает внутри пользовательской функции?

#r #function #rbind

#r #функция #rbind

Вопрос:

Я пытаюсь добавить строки к фрейму данных внутри пользовательской функции. Я делал это раньше в цикле for без труда, следующим образом:

 t1 <- data.frame(a=character(),
                 b=numeric())
for(i in 1:2){
    tmp.df <- data.frame(a="apple", b=i)
    t1 <- rbind(t1,tmp.df)
}
 

Я получаю фрейм данных с двумя наблюдениями.

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

 t1 <- data.frame(a=character(),
                 b=numeric())

create.rows <- function(id, it){
  if(it==1){
    
    tmp.df <- data.frame(a=id, b=it)
    t1 <- rbind(t1,tmp.df)
  }else{
    tmp.df <- data.frame(a=id, b=99)
    t1 <- rbind(t1,tmp.df)
  }
}
 

Почему это происходит и что я могу сделать, чтобы это исправить?

Обратите внимание, что я не знаю заранее, сколько строк будет в dataframe, поэтому я не могу записывать непосредственно в определенную строку.

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

1. «Это не работает». Что такое «это». Простое создание функции ничего не дает.

Ответ №1:

Внутри функции нужно указать <<- форму оператора присваивания, чтобы заставить R выполнять поиск по родительским средам, чтобы найти объект в левой части оператора присваивания и присвоить ему новое значение.

 t1 <- data.frame(a=character(),
                 b=numeric())

create.rows <- function(id, it){
     if(it==1){
          
          tmp.df <- data.frame(a=id, b=it)
          t1 <<- rbind(t1,tmp.df)
     }else{
          tmp.df <- data.frame(a=id, b=99)
          t1 <<- rbind(t1,tmp.df)
     }
}

create.rows(1,1)
create.rows(1,2)
t1
 

… и вывод:

 > t1
  a  b
1 1  1
2 1 99
 

Для получения дополнительной информации о поведении трех форм оператора присваивания ( = , <- и <<- ) просмотрите страницу справки для оператора присваивания, где в соответствующем разделе говорится:

Операторы <<- и ->> обычно используются только в функциях и вызывают поиск в родительских средах для существующего определения присваиваемой переменной. Если такая переменная найдена (и ее привязка не заблокирована), то ее значение переопределяется, в противном случае присвоение происходит в глобальной среде.

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

1.инструкция: нужно указать <<- форму оператора присваивания, чтобы заставить R выполнять поиск по родительским средам, чтобы найти объект в левой части оператора присваивания.вводит в заблуждение. Означает ли это, что <- , = , -> не выполняет поиск в родительских средах?? Я верю, что они это делают. Разница в том, что <<- переопределяет объект в среде (очевидно, когда привязка объекта разблокирована), а <- не

2. Привет @Onyambu. Я не согласен с вашей характеристикой моего ответа. Как я читал раздел 5.4 » Программное обеспечение для анализа данных «, целью <<- оператора является выполнение нелокального присваивания из функции, которая по определению переопределяет значение объекта в родительской среде.

3. Большое вам спасибо — я никогда раньше не сталкивался с этим оператором присваивания.

4. @Susan — всегда пожалуйста. Если вы нашли ответ полезным, пожалуйста, примите и / или поддержите его. Кстати, ответ Ронака Шаха также работает.

5. Это <- делает именно то, что вы указали выше. Вот почему я решил, что это утверждение вводит в заблуждение. Основное различие между <<- и <- заключается в том, что позже нельзя использовать для ПЕРЕОПРЕДЕЛЕНИЯ переменной. Вероятно, ваше сообщение должно гласить, что нужно указать <<- форму оператора присваивания, чтобы заставить R выполнять поиск в родительских средах, чтобы найти объект в левой части оператора присваивания И ПЕРЕОПРЕДЕЛИТЬ ЕГО

Ответ №2:

return измененный фрейм данных в конце функции.

 t1 <- data.frame(a=character(),
                 b=numeric())

create.rows <- function(id, it){

  if(it==1){
    tmp.df <- data.frame(a=id, b=it)
    t1 <- rbind(t1,tmp.df)
  }else{
    tmp.df <- data.frame(a=id, b=99)
    t1 <- rbind(t1,tmp.df)
  }
  return(t1)
}

t1 <- create.rows(1,1)
t1
#  a b
#1 1 1