理解变换

时间:2014-01-01 19:42:16

标签: r plyr

我收到有关转换功能基本用法的警告信息。我正在尝试将一个简单的自定义函数应用于数据框以创建一个新变量:

change <- function(x) {
   if (x==1) {
    y <- "Code A"
  } else if (x==2) {
    y <- "Code B"
  } else {
    y <- "none"
  }
  return(y)
}

然后我使用:

应用它
df_test2 <- transform(df, strX=change(x))

这给了我下面的警告,结果不正确(它创建了一个因素,所有内容都编码为“无”

Warning messages:
1: In if (x == 1) { :
  the condition has length > 1 and only the first element will be used
2: In if (x == 2) { :
  the condition has length > 1 and only the first element will be used

谁能告诉我我做错了什么?

3 个答案:

答案 0 :(得分:3)

结果不正确,因为函数change未向量化,并返回单个元素。这将反映x中的第一个向量条目,而不是其余的。返回的单个值将以通常的方式分配给列 - 复制单个返回的值以适合列。向量化函数是获得预期结果所需的。

要对此功能进行矢量化,您可以使用ifelse而不是if

change2 <- function(x) ifelse(x==1, "Code A", ifelse(x==2, "Code B", "none"))

对于对函数进行向量化非常简单的情况,有Vectorize函数包装器,用于创建一个只接受长度为1的参数的向量化函数。但是{{1}使用ifelse的原始定义将比Vectorize(change)表现更好。

使用矢量作为输入的原始定义会显示以下错误:

change

使用change(1:3) [1] "Code A" Warning message: In if (x == 1) { : the condition has length > 1 and only the first element will be used 来处理这种情况:

Vectorize

返回与上面定义的Vectorize(change)(1:3) [1] "Code A" "Code B" "none" 相同的内容:

change2

快速的速度比较显示change2(1:3) [1] "Code A" "Code B" "none" 解决方案确实更快:

ifelse

答案 1 :(得分:3)

我认为

sapply有效。但这可能是矫枉过正的。

这里是:

df <- data.frame(A=seq(1:5), 
          B=c('green', 'red', 'blue', 'blue', 'green'),
          C=rnorm(seq(1:5)))

数据帧

> df
  A     B          C
1 1 green -1.6728109
2 2   red  1.2073857
3 3  blue -0.8837428
4 4  blue  1.4519152
5 5 green -0.8218307

功能

change <- function(txt) {
    if (txt=='red') {
        res <- 'Code Red'
    }
    else if (txt=='blue') {
        res <- 'Code Blue'
    }
    else {
        res <- 'none'
    }
    return(res)
}

单字符串的用法

> change('green')
[1] "none"

B向量的用法。

> df$changed.B <- sapply(df$B, change)
> df
  A     B          C changed.B
1 1 green -1.6728109      none
2 2   red  1.2073857  Code Red
3 3  blue -0.8837428 Code Blue
4 4  blue  1.4519152 Code Blue
5 5 green -0.8218307      none

答案 2 :(得分:0)

马修的回答提出了另一个解决我问题的解决方案。我将我的功能改为:

change <- function(df) {
  if (df["x"]==1) {
    y <- "Code A"
  } else if (df["x"]==2) {
    y <- "Code B"
  } else {
    y <- "none"
  }
  return(y)
}

用apply修改变换:

df$f <-apply(df, 1,change)

这给了我想要的结果。