在R中生成具有多个条件的列值

Met*_*ics 5 loops r multiple-columns

我有一个数据框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
Run Code Online (Sandbox Code Playgroud)

#生成列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]}
Run Code Online (Sandbox Code Playgroud)

但是,我的问题是我想应用多个条件:

例如,我想得到这样的东西:

(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
Run Code Online (Sandbox Code Playgroud)

如何使用循环或任何其他方法获得第二个输出?

flo*_*del 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))
}
Run Code Online (Sandbox Code Playgroud)

请注意该decode函数是如何在SQL函数之后命名的.我希望像这样的函数成为基础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
Run Code Online (Sandbox Code Playgroud)

对于您的特定问题:

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
Run Code Online (Sandbox Code Playgroud)


Mat*_*erg 3

生成乘数向量:

tt <- rep(1, max(z$x))
tt[2] <- 2
tt[4] <- 4
tt[7] <- 3
Run Code Online (Sandbox Code Playgroud)

这是您的新专栏:

> 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
Run Code Online (Sandbox Code Playgroud)

如果 中有负值,这将不起作用z$x

已编辑

这是上述内容的概括,其中使用函数来生成乘数向量。事实上,我们创建一个基于参数的函数。

我们要转换以下值:

2 -> 2
4 -> 4
7 -> 3
Run Code Online (Sandbox Code Playgroud)

否则采用默认值 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
  }
}
Run Code Online (Sandbox Code Playgroud)

下面是我们如何使用它:

x <- c(2,4,7)
y <- c(2,4,3)

g <- f(1, x, y)
Run Code Online (Sandbox Code Playgroud)

g就是我们想要的功能。应该清楚的是,任何映射都可以通过xy参数提供给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
Run Code Online (Sandbox Code Playgroud)

应该清楚这仅适用于整数值。