5

データフレームがzあり、の2つの古い列の値に基づいて新しい列を作成したいと思います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

#列の値に4を掛けqた値に等しい列を生成します。他の値の場合は、列の値に等しくなります。tx=3xt

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

ループまたは他の方法を使用して2番目の出力を取得するにはどうすればよいですか?

4

8 に答える 8

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))
}

decodeSQL関数にちなんで関数の名前が付けられていることに注意してください。このような関数がベース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
于 2013-01-05T03:08:50.193 に答える
3

セニョールの提案に基づく:

> 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
于 2013-01-01T15:38:18.917 に答える
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

これは整数値に対してのみ機能することは明らかです。

于 2012-12-31T20:15:56.850 に答える
3

ifelseコマンドが1つだけの簡単な解決策は次のとおりです。

の乗数を計算し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
于 2013-01-07T10:13:05.613 に答える
2

flodelのブログに投稿された「dinre」という答えが本当に気に入りました。

for (i in 1:length(data_Array)){
data_Array[i] <- switch(data_Array[i], banana="apple", orange="pineapple", "fig")
}

switch整数引数のヘルプページを注意深く読むことについての警告付き。

于 2013-01-07T16:45:40.810 に答える
2

あなたはでそれを行うことができます

  • ベースR
  • 一行で
  • マッピングはコードで読み取るのが非常に明確です
  • ヘルパー関数なし(わかりました、無名関数)
  • アプローチはネガで機能します
  • アプローチは任意のアトミックベクトル(実数、文字)で機能します

このような:

> 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
于 2013-01-12T05:35:53.090 に答える
1

これを行うためにmatchを使用することもできます。散布図のポイントに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
于 2013-01-07T08:45:52.957 に答える
1

これはdecode、SQLバージョンと同じように動作する文字ベクトル(因子でテストされていない)用のRの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  

これが私が使用しているコードです。要点はここで最新の状態に保ちます(リンク)。

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)

}
于 2014-11-19T06:20:58.440 に答える