Как заставить код в моей функции возвращать отредактированные кадры данных - PullRequest
1 голос
/ 27 марта 2019

Я пытаюсь использовать операторы ifelse в R, чтобы добавить определенный префикс к моим фреймам данных.

У меня две проблемы с моим кодом на данный момент.

1) Когда я пытаюсь обернуть это в функцию, она не возвращает отредактированные фреймы данных.

2) параметр no = оператора ifelse, который я вставил, повторяется, какЯ делаю это только повторить один раз?

Буду признателен за любую помощь.

примечание.Я использую некоторые данные в этом примере по профессиональным причинам.


dput (head (Player1)):

structure(list(Class = structure(c(2L, 1L, 5L, 4L, 3L), .Label = c("fighter", 
"paladin", "rouge", "sorceror", "wizard"), class = "factor"), 
Race = structure(c(3L, 1L, 4L, 3L, 2L), .Label = c("elf", 
"gnome", "human", "orc"), class = "factor"), alignment = structure(c(4L, 
2L, 1L, 5L, 3L), .Label = c("CE", "CG", "LG", "NE", "NN"), class = "factor"), 
Level = c(6, 7, 1, 2, 4)), row.names = c(NA, 5L), class = "data.frame")

dput (head (Player2)):

structure(list(Class = structure(c(2L, 1L, 5L, 4L, 3L), .Label = c("fighter", 
"paladin", "rouge", "sorceror", "wizard"), class = "factor"), 
Race = structure(c(3L, 1L, 4L, 3L, 2L), .Label = c("elf", 
"gnome", "human", "orc"), class = "factor"), alignment = structure(c(4L, 
2L, 1L, 5L, 3L), .Label = c("CE", "CG", "LG", "NE", "NN"), class = "factor"), 
Level = c(6, 7, 1, 2, 4)), row.names = c(NA, 5L), class = "data.frame")

Допустим, у нас естьдва игрока Джон (player1) и Люси (player2), и мы хотим добавить префикс к их именам.Я добился этого с помощью кода ниже.

ifelse(test = grepl('Johns', names(Player1)) == F, 
         yes = colnames(Player1) <- paste('Johns', colnames(Player1), sep = '_'),
         no = print('Player info is fine'))

Вывод здесь работает, и все столбцы получают префикс «Johns_». Однако, когда я пытаюсь обернуть это в функцию для обоих игроков, кадры данных не меняются.

Функция:

Addnames <- function(Player1, Player2){
  ifelse(test = grepl('Johns', names(Player1)) == F, 
         yes = colnames(Player1) <- paste('Johns', colnames(Player1), sep = '_'),
         no = print('Player info is fine'))
  ifelse(test = grepl('Lucys', names(Player2)) == F, 
         yes = colnames(Player2) <- paste('Lucys', colnames(Player2), sep = '_'),
         no = print('Player info is fine'))
return(Player1)
return(Player2)
}

Addnames(Player1, Player2) 

Это не редактирует названия столбцов данных.


Мой идеальный вывод - иметь 'Johns_' и 'Lucys_'в качестве префикса имени каждого столбца для фреймов данных Player1 и Player2 соответственно.

Я хотел бы сделать это в функции.

Другая проблема, с которой я столкнулся, заключается в инструкции ifelse, если no = 'Информация об игроке в порядке' повторяется для каждого имени столбца.Как мне заставить это повторяться только один раз.

Опять же, любая помощь будет высоко ценится.

Ответы [ 3 ]

1 голос
/ 27 марта 2019

Просто используйте списки и запустите Map для поэтапной итерации между игроками и соответствующими кадрами данных без какой-либо условной логики ifelse.Даже используйте setNames для возврата в правую часть.

player_list <- c("John", "Lucy")    

df_list <- list(Player1, Player2)

# RENAME COLUMNS ELEMENTWISE
new_df_list <- Map(function(nm, df) setNames(df, paste0(nm, "_", colnames(df))),
                   player_list, df_list)

# OUTPUT DF ELEMENTS
new_df_list$John
#   John_Class John_Race John_alignment John_Level
# 1    paladin     human             NE          6
# 2    fighter       elf             CG          7
# 3     wizard       orc             CE          1
# 4   sorceror     human             NN          2
# 5      rouge     gnome             LG          4

new_df_list$Lucy
#   Lucy_Class Lucy_Race Lucy_alignment Lucy_Level
# 1    paladin     human             NE          6
# 2    fighter       elf             CG          7
# 3     wizard       orc             CE          1
# 4   sorceror     human             NN          2
# 5      rouge     gnome             LG          4
1 голос
/ 27 марта 2019

Если у вас более двух игроков, вам, вероятно, понадобится функция многократного использования.Подобно вышеописанному решению от fmarm, но переработке больше вашего исходного кода:

Addnames <- function(player, namestring){
  ifelse(test = grepl(namestring, names(player)) == F, 
         yes = colnames(player) <- paste(namestring, colnames(player), sep = '_'),
         no = print('Player info is fine'))
  return(player)
}


Player1 <- Addnames(player=Player1, namestring="Johns")
Player2 <- Addnames(player=Player2, namestring="Lucys")

Редактировать: далее, если допустить, что «Lucys» на самом деле называется «Lucy», добавление «s» может, конечно, такжебыть сделано в функции:

Addnames <- function(player, namestring){
  ifelse(test = grepl(namestring, names(player)) == F, 
         yes = colnames(player) <- paste(namestring, "s", colnames(player), sep = '_'),
         no = print('Player info is fine'))
  return(player)
}


Player1 <- Addnames(player=Player1, namestring="John")
Player2 <- Addnames(player=Player2, namestring="Lucy")
1 голос
/ 27 марта 2019

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

Addnames <- function(player_df,player_name){
   column_names_to_change <- which(!grepl('Johns', names(player_df)))
   colnames(player_df)[column_names_to_change]  <- paste(player_name,colnames(player_df)[column_names_to_change],sep="_")
   return(player_df)
}

Чтобы изменить фрейм данных после функции, необходимо переназначить результат обратно на Player1

Player1 <- Addnames(Player1,"Johns")
Player2 <- Addnames(Player2,"Lucys")
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...