我有一个数据框z
,我想根据两个旧列z
的值创建新列。以下是这个过程:
>z<-cbind(x=1:10,y=11:20,t=21:30)
> z<-as.data.frame(z)
>z
x y t
1 1 11 21
2 2 12 22
3 3 13 23
4 4 14 24
5 5 15 25
6 6 16 26
7 7 17 27
8 8 18 28
9 9 19 29
10 10 20 30
#生成列q
,其等于列t
的值乘以{4} x=3
,而对于x
的其他值,则等于值列t
。
for (i in 1:nrow(z)){
z$q[i]=if (z$x[i]==4) 4*z$t[i] else z$t[i]}
但是,我的问题是我想要应用多个条件:
例如,我想得到这样的东西:
(If x=2, q=t*2; x=4, q=t*4; x=7, q=t*3; for other it is equal to t)
> z
x y t q
1 1 11 21 21
2 2 12 22 44
3 3 13 23 23
4 4 14 24 96
5 5 15 25 25
6 6 16 26 26
7 7 17 27 81
8 8 18 28 28
9 9 19 29 29
10 10 20 30 30
如何使用循环或任何其他方法获取第二个输出?
答案 0 :(得分:10)
通过递归构建嵌套的ifelse
函数,您可以获得到目前为止提供的两种解决方案的好处:ifelse
速度快,可以处理任何类型的数据,而@ Matthew的解决方案更多功能性但仅限于整数且可能很慢。
decode <- function(x, search, replace, default = NULL) {
# build a nested ifelse function by recursion
decode.fun <- function(search, replace, default = NULL)
if (length(search) == 0) {
function(x) if (is.null(default)) x else rep(default, length(x))
} else {
function(x) ifelse(x == search[1], replace[1],
decode.fun(tail(search, -1),
tail(replace, -1),
default)(x))
}
return(decode.fun(search, replace, default)(x))
}
注意如何在SQL函数之后命名decode
函数。我希望这样的函数能够成为基础R包...以下是一些说明其用法的例子:
decode(x = 1:5, search = 3, replace = -1)
# [1] 1 2 -1 4 5
decode(x = 1:5, search = c(2, 4), replace = c(20, 40), default = 3)
# [1] 3 20 3 40 3
针对您的特定问题:
transform(z, q = decode(x, search = c(2,4,7), replace = c(2,4,3), default = 1) * t)
# x y t q
# 1 1 11 21 21
# 2 2 12 22 44
# 3 3 13 23 23
# 4 4 14 24 96
# 5 5 15 25 25
# 6 6 16 26 26
# 7 7 17 27 81
# 8 8 18 28 28
# 9 9 19 29 29
# 10 10 20 30 30
答案 1 :(得分:3)
生成多重向量:
tt <- rep(1, max(z$x))
tt[2] <- 2
tt[4] <- 4
tt[7] <- 3
这是你的新专栏:
> z$t * tt[z$x]
[1] 21 44 23 96 25 26 81 28 29 30
> z$q <- z$t * tt[z$x]
> z
x y t q
1 1 11 21 21
2 2 12 22 44
3 3 13 23 23
4 4 14 24 96
5 5 15 25 25
6 6 16 26 26
7 7 17 27 81
8 8 18 28 28
9 9 19 29 29
10 10 20 30 30
如果z$x
中存在负值,则无效。
<强>被修改强>
以上是对上述内容的概括,其中函数用于生成乘数向量。实际上,我们根据参数创建了一个函数。
我们希望转换以下值:
2 -> 2
4 -> 4
7 -> 3
否则将采用默认值1。
这是一个生成所需功能的函数:
f <- function(default, x, y) {
x.min <- min(x)
x.max <- max(x)
y.vals <- rep(default, x.max-x.min+1)
y.vals[x-x.min+1] <- y
function(z) {
result <- rep(default, length(z))
tmp <- z>=x.min & z<=x.max
result[tmp] <- y.vals[z[tmp]-x.min+1]
result
}
}
以下是我们如何使用它:
x <- c(2,4,7)
y <- c(2,4,3)
g <- f(1, x, y)
g
是我们想要的功能。应该清楚的是,任何映射都可以通过x
和y
参数提供给f
。
g(z$x)
## [1] 1 2 1 4 1 1 3 1 1 1
g(z$x)*z$t
## [1] 21 44 23 96 25 26 81 28 29 30
应该清楚这只适用于整数值。
答案 2 :(得分:3)
基于Señor的建议:
> z$q <- ifelse(z$x == 2, z$t * 2,
ifelse(z$x == 4, z$t * 4,
ifelse(z$x == 7, z$t * 3,
z$t * 1)))
> z
x y t q
1 1 11 21 21
2 2 12 22 44
3 3 13 23 23
4 4 14 24 96
5 5 15 25 25
6 6 16 26 26
7 7 17 27 81
8 8 18 28 28
9 9 19 29 29
10 10 20 30 30
答案 3 :(得分:3)
这是一个只有一个ifelse
命令的简单解决方案:
计算t
的乘数:
ifelse(z$x == 7, 3, z$x ^ (z$x %in% c(2, 4)))
完整的命令:
transform(z, q = t * ifelse(x == 7, 3, x ^ (x %in% c(2, 4))))
x y t q
1 1 11 21 21
2 2 12 22 44
3 3 13 23 23
4 4 14 24 96
5 5 15 25 25
6 6 16 26 26
7 7 17 27 81
8 8 18 28 28
9 9 19 29 29
10 10 20 30 30
答案 4 :(得分:2)
我真的很喜欢这个答案&#34; dinre&#34;发布到flodel的博客:
for (i in 1:length(data_Array)){
data_Array[i] <- switch(data_Array[i], banana="apple", orange="pineapple", "fig")
}
警告有关读取switch
的帮助页面的整数参数。
答案 5 :(得分:2)
你可以在
中完成> transform(z,q=t*sapply(as.character(x),function(x) switch(x,"2"=2,"4"=4,"7"=3,1)))
x y t q
1 1 11 21 21
2 2 12 22 44
3 3 13 23 23
4 4 14 24 96
5 5 15 25 25
6 6 16 26 26
7 7 17 27 81
8 8 18 28 28
9 9 19 29 29
10 10 20 30 30
答案 6 :(得分:1)
您也可以使用匹配来执行此操作。我倾向于使用这一点,同时将col,pch和cex等参数分配给散点图中的点
searchfor<-c(2,4,7)
replacewith<-c(2,4,3)
# generate multiplier column
# q could also be an existing vector where you want to replace certain entries
q<-rep(1,nrow(z))
#
id<-match(z$x,searchfor)
id<-replacewith[id]
# Apply the matches to q
q[!is.na(id)]<-id[!is.na(id)]
# apply to t
z$q<-q*z$t
答案 7 :(得分:1)
这里是R中用于字符向量(未经测试的因子)的SQL decode
版本,其运行方式与SQL版本相同。即它需要任意数量的目标/替换对,以及作为默认值的可选的最后一个参数(注意默认值不会覆盖NA)。
我可以看到它与dplyr
mutate
操作一起使用非常有用。
> x <- c("apple","apple","orange","pear","pear",NA)
> decode(x, apple, banana)
[1] "banana" "banana" "orange" "pear" "pear" NA
> decode(x, apple, banana, fruit)
[1] "banana" "banana" "fruit" "fruit" "fruit" NA
> decode(x, apple, banana, pear, passionfruit)
[1] "banana" "banana" "orange" "passionfruit" "passionfruit" NA
> decode(x, apple, banana, pear, passionfruit, fruit)
[1] "banana" "banana" "fruit" "passionfruit" "passionfruit" NA
以下是我正在使用的代码,我要及时了解最新信息(link)。
decode <- function(x, ...) {
args <- as.character((eval(substitute(alist(...))))
replacements <- args[1:length(args) %% 2 == 0]
targets <- args[1:length(args) %% 2 == 1][1:length(replacements)]
if(length(args) %% 2 == 1)
x[! x %in% targets & ! is.na(x)] <- tail(args,1)
for(i in 1:length(targets))
x <- ifelse(x == targets[i], replacements[i], x)
return(x)
}