替代case_when()将函数分配给R中的变量的方法

时间:2018-07-24 04:15:47

标签: r case-when

一个(我希望)非常简单的问题。我想使用case_when()或与其等效的东西作为一种干净的解决方案,以基于变量的值分配要使用的函数。所以,我想做这样的事情:

library(tidyverse)
library(lubridate)
library(nycflights13)
#small data frame of new years day flights from JFK
df1<-flights %>% filter(year==2013,month==1,day==1,origin=="JFK")  

#use min_ind as an indicator (in practice this would be a variable from my dataset
min_ind<-1

现在,我想要一种简单的方法来根据min_ind的值将函数分配给func_test。我可以这样做:

  if(min_ind==1)
    func_test<-min
  if(min_ind!=1)
    func_test<-max
#test it
func_test(df1$distance)
#reverse
min_ind<-0
  if(min_ind==1)
     func_test<-min
  if(min_ind!=1)
     func_test<-max
func_test(df1$distance)

这很好。当min_ind为1时,我得到最小值;当它不是1时,我得到最大值。我想做的是通过case_when()进行此赋值,因为我有一组4或5个函数,所以我可能想对数据中的值使用条件。这样可能吗?

func_test<-case_when(
  min_ind==1 ~ min,
  min_ind!=1 ~ max
)

我收到一个错误代码,错误代码为value [[1]] [rep(NA_integer_,m)]:   类型为“ builtin”的对象不可子集化

谢谢您的建议。

3 个答案:

答案 0 :(得分:3)

case_when实际上被设计为矢量化函数。因此,公式项的两侧都应是类似矢量的东西,且长度相同或可回收。函数的行为不像集合。问题是,如果min_ind不是长度为1的向量,事情就会变得混乱。基本上,它正在尝试检查长度是否兼容。查看您在这里看到的错误消息

min_ind <- 1
func_test<-case_when(
  min_ind==1 ~ 1:3,
  min_ind!=1 ~ 4:6
)
# Error: RHS of case 1 (1:3) must be length 1 (the first output), not 3

因此,您最初收到的错误消息基本上是因为它试图将函数的长度扩展到与输入相同的长度,这再次对函数没有意义。您可以将函数填充到列表中,然后在确定length(min_ind==1)

时提取第一个元素
min_ind <- 1
func_test<-case_when(
  min_ind==1 ~ list(min),
  min_ind!=1 ~ list(max)
)[[1]]

答案 1 :(得分:1)

如果您查看func_test<-case_when( min_ind==1 ~ list(min), min_ind!=1 ~ list(max) )[[1]] 的内部,您会发现它正在尝试将RHS值视为一个列表,使用基本函数时R会不喜欢RHS值。这是解决它的方法:

<div class="container">
  <div id="foo"></div>
</div>
<h1>content below</h1>

此解决方案将功能放入它们自己的列表中,然后在将其分配给func_test之前将其提取。

答案 2 :(得分:0)

好吧,您的错误是min在上述代码中未引用任何内容。 应该是:

func_test<-case_when(
   min_ind==1 ~ min(df1$distance),
   TRUE ~ max(df1$distance)
)

TRUE仅在其他一个选项时使用:索引可以为1或不为1。

这有效;)