我收到有关转换功能基本用法的警告信息。我正在尝试将一个简单的自定义函数应用于数据框以创建一个新变量:
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
谁能告诉我我做错了什么?
答案 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)
这给了我想要的结果。