在给定列上应用函数

时间:2014-07-04 04:21:12

标签: r dataframe apply

我想应用一个给定的函数" passFailFunc"在我的dataFrame的给定列上。 这是一个例子:

df <- data.frame(A = letters[1:10], B = sample(1:20, 10))
=> 
   A  B
1  a  7
2  b 15
3  c  4
4  d  9
5  e 17
6  f  8
7  g 18
8  h 14
9  i 16
10 j 12

和功能定义

passFailFunc <- function(x, th) {
  if (x>th) { 
    status='fail'
  } else {
    status='pass'
  }
  status
}

我想创建一个新列&#34; status&#34;其中B列的数字被认为是&#39;通过&#39;如果它们低于阈值,则说th = 15,否则

df$status <- lapply(df$B, function(x) passFailFunc(x, 15))
=> 
   A  B status
1  a  7   pass
2  b 15   pass
3  c  4   pass
4  d  9   pass
5  e 17   fail
6  f  8   pass
7  g 18   fail
8  h 14   pass
9  i 16   fail
10 j 12   pass

这很好,似乎在做这项工作。但是,当我尝试:

factor(df$status)

Error in sort.list(y) : 'x' must be atomic for 'sort.list'
Have you called 'sort' on a list?

状态列实际上是一个向量

> is.vector(df$status)
[1] TRUE

问题:如何正确生成&#39;状态&#39;专栏?

2 个答案:

答案 0 :(得分:2)

lapply只是一个漂亮的for循环,尝试在R中避免使用它们总是更好。您的特定函数可以使用ifelse

轻松进行矢量化
df$status <- ifelse(df$B > 15, "fail", "pass")

如果您仍然希望将其用作功能,则可以尝试使用data.table

passFailFunc <- function(x, th) {
  ifelse (x > th, "fail", "pass")
}

library(data.table)
setDT(df)[, status := lapply(.SD, function(x) passFailFunc(x, 15)), .SDcols = "B"]

factor(df$status)对您不起作用的原因是因为lapply返回了一个列表(阅读?lapply文档),您可以使用str(df)查看它。如果您仍想以原始方式执行此操作,请使用sapply代替lapply

is.vector(df$status)返回TRUE的原因是因为list是R中的向量。

尝试运行

is.vector(list(a=1))
## [1] TRUE

答案 1 :(得分:1)

您可以通过以下方式避免错误:

set.seed(1)
df <- data.frame(A = letters[1:10], B = sample(1:20, 10)) 

使用您的passFailFunc

df$status <- unlist(lapply(df$B, function(x) passFailFunc(x, 15)))
factor(df$status)
#[1] pass pass pass fail pass pass pass pass fail pass
#Levels: fail pass

factor(df$B<=15, labels=c('fail', 'pass'))
#[1] pass pass pass fail pass pass pass pass fail pass
#Levels: fail pass

c('pass', 'fail')[(df$B>15) +1]
#[1] "pass" "pass" "pass" "fail" "pass" "pass" "pass" "pass" "fail" "pass"