如何使函数中的代码返回已编辑的数据帧

时间:2019-03-27 13:54:50

标签: r function if-statement

我正在尝试在R中使用ifelse语句向我的数据帧添加特定的前缀。

我的代码目前有两个问题。

1)当我尝试将其包装到函数中时,它不会返回已编辑的数据帧。

2)我输入的ifelse语句的no =参数本身会重复,如何使它仅重复一次?

不胜感激。

注意。由于专业原因,我在此示例中使用了一些组合数据。


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")

假设我们有两个球员John(玩家1)和Lucy(玩家2),我们想在他们的姓氏上添加一个前缀。我通过使用下面的代码实现了这一点。

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) 

这不会编辑数据框的名称。


我的理想输出是在Player1和Player2数据帧的每个列名称上分别以'Johns_'和'Lucys_'作为前缀。

我会在函数中做到这一点。

我遇到的另一个问题是ifelse语句中是否没有='播放器信息很好'对每个列名重复其自身。我如何才能只重复一次。

再次获得帮助将不胜感激。

3 个答案:

答案 0 :(得分:1)

如果您真的想在函数中执行此操作,我宁愿创建一个带有两个参数的函数:数据框的名称和播放器的名称,因此只返回一件事:具有正确参数的数据框列名

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")

答案 1 :(得分:1)

仅使用列表并运行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

答案 2 :(得分:1)

假设您有两个以上的播放器,则可能需要可重复使用的功能。与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")

编辑:进一步假设“露西”实际上被称为“露西”,那么当然也可以在函数中添加“ 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")