在用户定义的函数R

时间:2018-06-29 18:47:06

标签: r dataframe

我正在尝试将整数(“ i”)传递给其中将“ i”用作数据帧的行索引的函数。但是,这样做...

user_definedFUN <- function (i){
  ...
  result <- df[i, "col_name"]
  ...
}

x <- user_definedFUN(1)

...产生以下错误:

Error in `[.data.frame`(df, i, "col_name") : 
object 'i' not found

我确定这是一个简单的问题,即如何在方括号内引用“ i”(即使不够简单,我无法找到解决方案);但是,如有必要,我在下面提供了其他详细信息。

data.frame:

gen_name <- c("Boomers","Gen X","Millenials","Gen Z")
gen_years <- c("1946 to 1964","1965 to 1980","1981 to 1996", "1997 to 2011")
gen_xmin <- c(11, 9, 5, 2)
gen_xmax <- c(15, 11, 8, 5)
GEN_G.labels <- data.frame(gen_name, gen_years, gen_xmin, gen_xmax)

data.frame包含四代的信息,这些信息将用于按年龄绘制ggplot人口图上的矩形作为图层。

矩形将通过以下函数创建,该函数将从循环中调用,并提供特定生成的行索引(1 =“ Boomers”,2 =“ Gen X”等)

genlabelsFUN <- function(i){
  # return a geom_rect()
  rv <- geom_rect(aes(
       xmin = GEN_G.labels[i, "gen_xmin"],
       xmax = GEN_G.labels[i, "gen_xmax"],
       ymin = 1000, 
       ymax = 1100)
     , fill = "red")
  return(rv)
}

ggplot(...snip...) +
   ...snip... +
   genlabelsFUN(1)

如果使用静态索引值,该函数将起作用。例如,用'GEN_G.labels [ 1 ,“ gen_xmin”]'代替'GEN_G.labels [ i ,“ gen_xmin”]'在11和在x轴上为15,在y轴上为1,000,高度为100。尽管如此,如果没有“ i”的动态方面,该函数将毫无意义。

下图显示了使用静态索引值时的输出(注意:为简单起见,我在上面的示例中使用了不同的y轴刻度)。最终代码将遍历GEN_G.labels的每一行,并运行genlabelsFUN()为每一代创建一个相似的矩形。​​

population age chart with red box indicating boomer generation

谢谢

编辑:

完整ggplot

scaleFUN <- function(x) formatC( x / 1000, format = "f", big.mark = ",", digits = 0) #format as thousands with comma

ggplot(data = GEN_G.data_frame, aes(x = range, y = persons)) +
  geom_bar(stat = "identity") +
  theme_classic() +
  theme(
    axis.text.x = element_text(angle = 90, hjust = 1)) +
  scale_y_continuous(
    name = "Persons (thousands)",
    labels = scaleFUN) +
  genlabelsFUN(1)

编辑2:

可复制的示例(基于下面的MrFlick注释起作用)

GEN_G.dataframe <- data.frame(
  range = c(1:21), 
  persons = abs(rnorm(21))*50)

GEN_G.labelsx <- data.frame(
  gen_name = c("Group A","Group B","Group C","Group D"), 
  gen_xmin = c(11, 9, 5, 2), 
  gen_xmax = c(15, 11, 9, 5))
GEN_G.labelsx$gen_name <- factor(
  GEN_G.labelsx$gen_name, 
  levels = GEN_G.labelsx$gen_name)


ggplot() +
  geom_bar(data=GEN_G.dataframe,aes(x=range, y=persons),stat="identity") +
  theme_classic() +
  theme(
    axis.text.x = element_text(angle = 90, hjust = 1)) +
  geom_rect(aes(
    xmin = gen_xmin,
    xmax = gen_xmax,
    ymin = 175, 
    ymax = 180,
    fill = gen_name),
    data = GEN_G.labelsx)

“编辑2”示例的输出。

enter image description here

1 个答案:

答案 0 :(得分:0)

您不能在i中使用像aes()这样的变量。在aes()内的符号不会被评估,直到实际绘制绘图为止。如果以这种方式定义i,那么R就无法正确捕获环境,因此在绘制图形时该值将已更改。

但是,我什至不认为循环/函数甚至不是必需的。您应该能够做到

geom_rect(aes(xmin=gen_xmin, xmax=gen_xmax), ymin=1000, ymax=1000, data=GEN_G.labels)

对该层使用不同的data.frame。然后立即绘制所有框,而无需循环。