【问题标题】:Calling user inputs prompted through one R function in a second R function在第二个 R 函数中调用通过一个 R 函数提示的用户输入
【发布时间】:2015-10-29 22:27:51
【问题描述】:

非常感谢您提前帮助我 - 我是 R 编程的新手,并且一直在尝试使用通过另一个函数接受的用户输入。第二个函数是一个简单的工资计算器,其中三个变量是小时数、每小时工资率以及一旦工作时间数超过 180 时工资率相乘的次数。我编写了第一个名为 enterval 的函数,通过它我我要求用户输入上述变量。在称为薪水的第二个函数中,我试图在运行支付计算之前使用 enterval 接受输入。我被卡住了,因为当我遇到“if”条件时,第二个函数salary 正在中断,指定 if h > 180。我在下面分享我的代码。再次感谢您的友好帮助。我在以前的答案中进行了搜索,但找不到完全回答我的查询的特定实例 - 如果我错过了适当的先前回复,我深表歉意。 我在运行此代码时遇到的错误是“h > 180 中的错误: 比较 (6) 仅适用于 atomic 和 list 类型"

enterval <- function()  {
h <- (readline("Please enter number of hours: "))
h <- as.integer(h)
r <- (readline("Please enter applicable rate: "))
r <- as.integer(r)
m <- (readline("Please confirm your multiplier: "))
m <- as.integer(m)
}
salary <- function ()  {
    enterval()
    if (h > 180)  {
        totalpay <- (180*r) + ((h-180)*r*m)
        }
    else  {
        totalpay <- (h*r)
        }
    totalpay
}

【问题讨论】:

  • 非常感谢大家的大力帮助。答案确实打开了 R 中函数内函数的概念。我尝试了各种解决方案并得到了我需要的结果,以及一些我根本不知道的高级选项。向您提供最诚挚的帮助。

标签: r function user-input readline


【解决方案1】:

我认为你需要的是这样的功能:

enterval <- function()  {
  h <- (readline("Please enter number of hours: "))
  h <- as.numeric(h)
  r <- (readline("Please enter applicable rate: "))
  r <- as.numeric(r)
  m <- (readline("Please confirm your multiplier: "))
  m <- as.numeric(m)
  list(h=h, r=r, m=m)
}

salary <- function ()  {
  inputs <- enterval()
  if (inputs$h > 180)  {
    totalpay <- (180*inputs$r) + ((inputs$h-180)*inputs$r*inputs$m)
  }
  else  {
    totalpay <- (inputs$h*inputs$r)
  }
  totalpay
}

输出:

> salary()
Please enter number of hours: 5
Please enter applicable rate: 0.5
Please confirm your multiplier: 2
[1] 2.5

在您的问题中,enterval 只是返回了存储在m 中的值,但即使这样也没有保存在任何地方(因为您没有将其分配给salary 中的变量,因此salary 无法使用它. 在 R 函数中,只返回最后一个对象(或者函数 return 返回的对象,如果使用的话)。在上面的函数中,我返回一个包含元素 hrm 的列表。

然后我将该列表保存到inputssalary 可以使用它。可以使用$ 运算符访问inputs 中的元素。

另外,作为一个小补充,当你说比率时,我相信它是一个介于 0-1 之间的数字,所以我将as.integer 更改为as.numeric,因为as.integer 将向下舍入为整数。如果您确实需要一个整数,请随意将其改回 as.integer

编辑

更好,可能更高级的写作方式salary

根据@RichardScriven 的评论,避免输入所有input$* 变量的好方法是像这样使用list2env

salary <- function ()  {
  inputs <- enterval()
  list2env(inputs, environment())
  if (h > 180)  {
    totalpay <- (180*r) + (h-180)*r*m)
  }
  else  {
    totalpay <- (h*r)
  }
  totalpay
}

list2env 本质上将在薪水环境中的列表元素之外创建变量,无需使用input$* 即可立即访问这些变量。

【讨论】:

  • 您可以在salary() 中的inputs &lt;- enterval() 下添加list2env(inputs, environment()),而不必编写所有inputs$ 子集,因为hrm 将起作用环境变量。
  • @RichardScriven 谢谢这是一个有效的评论,我正在考虑是否使用它,然后我认为对于现在开始使用 R 的人来说可能太多了。不过我会添加它。
  • 实际上,如果您想变得非常时髦,您可以使用list2env(enterval(), environment()) 并删除inputs 分配。但这对于新人来说可能有点过于时髦了;)
  • @RichardScriven Wicked!
  • 非常感谢大家的大力帮助。答案确实打开了 R 中函数内函数的概念。我尝试了各种解决方案并得到了我需要的结果,以及一些我根本不知道的高级选项。向您提供最诚挚的帮助。
【解决方案2】:

在 R 函数中分配的变量(类似于许多其他编程语言)的范围有限,这意味着您在函数中分配的 m 将仅在该函数中可用。如果您希望您的变量在函数之外可用,您有两个主要选择:

  1. 返回变量,这是首选选项,由于许多堆栈溢出帖子中描述的众多原因,它更简洁且是良好的编程习惯。需要记住的重要一点是函数只能返回一个变量。

  2. 您可以进行全局赋值,这将使函数中的变量具有全局范围,并且可以在所有函数中访问。这个代码是m &lt;&lt;- 1,而不是m &lt;- 1。由于各种原因,不建议这样做。有关此主题的更多信息,请参阅 Global variables in RGlobal and local variables in R

由于您只能返回一个变量,您可以将所有三个对象放入数据框或列表中并返回。尽管我会质疑您是否希望在函数中完成值输入。此外,如果您的目标主要是用户输入,R 可能不是正确的语言。话虽这么说,下面的代码完成了你正在寻找的东西

enterval <- function()  {
  h <- (readline("Please enter number of hours: "))
  h <- as.integer(h)
  r <- (readline("Please enter applicable rate: "))
  r <- as.integer(r)
  m <- (readline("Please confirm your multiplier: "))
  m <- as.integer(m)
  salaryVariables <- data.frame("hours" = h, "rate" = r, "multiplier" = m)
  return(salaryVariables)
}
salary <- function(salaryInfo)  {
  r <- salaryInfo$rate
  h <- salaryInfo$hours
  m <- salaryInfo$multiplier
  if (h > 180)  {
    totalpay <- (180*r) + ((h-180)*r*m)
  }
  else  {
    totalpay <- (h*r)
  }
  return(totalpay)
}

mySalary <- enterval()
salary(mySalary)

【讨论】:

  • salary(mySalary) 不适用于salary 的定义方式。
  • 感谢您指出我在更改显然给我带来麻烦的功能之前一直在玩全局分配。
  • 非常感谢大家的大力帮助。答案确实打开了 R 中函数内函数的概念。我尝试了各种解决方案并得到了我需要的结果,以及一些我根本不知道的高级选项。向您提供最诚挚的帮助。
猜你喜欢
  • 1970-01-01
  • 2015-03-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-30
  • 1970-01-01
相关资源
最近更新 更多