R: применение функции к каждому элементу фрейма данных

#r #function

#r #функция

Вопрос:

Например, давайте использовать следующий фрейм данных, состоящий из строк:

 df <- data.frame(X = LETTERS[1:3], Y = LETTERS[4:6], row.names = c("r1", "r2", "r3"), stringsAsFactors = F)

> df
   X Y
r1 A D
r2 B E
r3 C F
  

Теперь я хотел бы применить эту функцию к каждому элементу фрейма данных:

 my_f <- function(x) paste0(x, x)
  

Что должно привести к такому результату:

 >df
    X  Y
r1 AA DD
r2 BB EE
r3 CC FF
  

Я использовал вложенные циклы for:

 for (i in 1:dim(df)[1]) {
    for (j in 1:dim(df)[2]) {
        df[i, j] = my_f(df[i, j])
    }
}
  

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

Ответ №1:

Мы можем использовать strrep , перебирая столбцы dataset с lapply помощью . [] Это восстановит ту же структуру ‘data.frame’.

 df[] <- lapply(df, strrep,2)
df
#   X  Y
#r1 AA DD
#r2 BB EE
#r3 CC FF
  

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

1. @agenis Да, я думаю strrep , должно быть быстрее

2. Не могли бы вы объяснить разницу между df и df[] ? Если я использую df[]<-apply(df,2,my_f) его, он работает, но без [] него теряются имена строк.

Ответ №2:

Вот решение без какой-либо apply-функции:

 df[] <- my_f(as.matrix(df))
  

Ответ №3:

У вас уже есть ответ.

Вы можете apply использовать свою функцию my_f для каждого элемента rowwise ( margin = 1 )

 data.frame(t(apply(df, 1,my_f)))

#    X1 X2
#r1 AA DD
#r2 BB EE
#r3 CC FF
  

И, как предложил @m0h3n, вы можете избежать t шага ранспозиции, применив функцию по столбцам ( margin=2 )

 data.frame(apply(df, 2,my_f))
  

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

1. Если вы выберете margin=2 , вам не нужно будет переносить.

2. Просто примечание, только это решение не требует df[] <- присваивания для создания data.frame , т. Е. Вы можете сделать new_df <- apply(df, 2, my_f) .

Ответ №4:

Использование циклов for

 for(i in 1:nrow(df)){
  df$X[i] <- paste0(df$X[i],df$X[i],collapse = "")
  df$Y[i] <- paste0(df$Y[i],df$Y[i],collapse = "")
}

print(df)

  X  Y
r1 AA DD
r2 BB EE
r3 CC FF