2011-12-08 160 views
1

我有一個簡單的問題:我有兩個函數。他們都使用if if else

if(...) {expression} 
if(...) {expression} 
if(...) {expression} 

代替

if(...) {expression} 
else{ 
     if(...) {expression} 
     else {expression} 
} 

但只有兩部作品之一。

第一個完美的作品:

test.1 <- function (y) { 
if(y == 1){z <- 10} 
if(y == 2){z <- 20} 
if(y == 5){z <- 50} 

return(z) 
} 

第二個不工作:

df.1 <- data.frame(A = 1:3) 
df.2 <- data.frame(A = 4:6) 
df.3 <- data.frame(A = 7:9) 

test.2 <- function (num) { 
    x <- with(if(num == 1){df.1} 
      if(num == 2){df.2} 
      if(num == 3){df.3}, {sum(A)}) 
return(x) 
} 

我需要使用如果爲了獲得第二個功能工作其他表達式:

test.2 <- function (num) { 
    x <- with(if(num == 1){df.1} 
      else {if(num == 2){df.2} 
        else {df.3} 
        }, {sum(A)}) 
    return(x) 
} 

我真的不明白爲什麼這個多重if語句在第一種情況下工作,但不在t中他第二個!?

+0

你有沒有采取如果出x < - 部分。 因此,如果設置了一個變量,然後您在x < - 與部分使用? –

+0

是的,我已經嘗試過。它可以工作,但在我的真實代碼中,with(...)部分有200行代碼,這意味着如果我這樣做,我可以獲得600行代碼而不是200行。這就是爲什麼我想插入if在()內部的正確位置。 –

+0

最根本的問題是你的第二個函數不是任何類似於正確的R語法的東西。你基本上要求它爲if(num == 1){df.1} if(num == 2){df.2} if(num == 3){df.3},{sum( A)})'即兩個參數與(),這只是在這種情況下的垃圾。改用'switch'。 'if'的設計目的不是爲了返回值,所以{}中的data.frames會打印出來,而不是像我想象的那樣分配給'x'。 –

回答

4

因爲with的第一個參數應該是「一個環境,一個列表,數據幀中的第二個例子是不行的,或者如在sys.call中的整數「(參見參數部分?with)。

您可以通過包裝避免錯誤「行意外結束的」如果在大括號聲明:

test.2 <- function (num) { 
    x <- with({if(num == 1)df.1 
      if(num == 2)df.2 
      if(num == 3)df.3}, {sum(A)}) 
    return(x) 
} 

但是,這仍然是行不通的,因爲你有括號內3倍的表達,只有最後一個評估後的表達式將被返回。那麼,它將工作,如果num==3 ...但我們可以做得更好。你可以使用switch這裏來代替:

test.2 <- function (num) { 
    with(switch(num, df.1, df.2, df.3), sum(A)) 
} 
0

所有三個expression都可能執行。

if(...) {expression} 
if(...) {expression} 
if(...) {expression} 

在以下情況下,只有一個expression將執行。

if(...) {expression} 
else 
{   
    if(...) {expression}   
    else 
    { 
     expression 
    } 
} 
+0

一般而言,你是可靠的。但這不是問題。如果您嘗試運行上面發佈的代碼(test.2),您會看到R出現「意外行尾」等錯誤。 –

+0

哦,這是R.它不是我目前的一杯茶。 – Azodious

1

你可能使用switch會更好:

test.2 <- function(num){ 
x <- with(switch(num,df.1,df.2,df.3),{sum(A)}) 
return(x) 
} 


test.2(1) 
[1] 6 
test.2(2) 
[1] 15 
test.2(3) 
[1] 24 
1

兩個問題:首先,with期望一個表達式(即evaulates到data.frame或環境)的第一個參數。您可以通過將大括號中的if語句包裝成單個表達式來解決該問題。

test.2 <- function (num) { 
    x <- with(
    { 
     if(num == 1){df.1} 
     if(num == 2){df.2} 
     if(num == 3){df.3} 
    }, 
    sum(A) 
) 
    return(x) 
} 

第二個問題是,在找到匹配項後,您沒有從表達式返回。所以當num是1時,如果滿足第一個條件並且返回df.1。但是接下來if表達式被計算,並且由於num不是2,所以返回NULL。同樣,第三個if表達式返回NULL。由於這是塊中的最後一個表達式,所以返回。您有有效

with(NULL, sum(A)) 

這是一樣的只是sum(A),因爲A不存在會拋出一個錯誤。

你可以讓另一補丁一樣

test.2 <- function (num) { 
    x <- with(
    { 
     if(num == 1)return(df.1) 
     if(num == 2)return(df.2) 
     if(num == 3)return(df.3) 
    }, 
    sum(A) 
) 
    return(x) 
} 

但你好得多使用switch相反,像詹姆斯暗示(當num是1,2或3這個工程)。


如果所有的數據幀都統一進行命名,如示例,那麼就比使用switch一個更好的解決方案。使用paste獲取變量名稱,然後致電get

test.3 <- function(num) with(get(paste("df", num, sep = ".")), sum(A)) 
test.3(1) #6 
test.3(2) #15 
test.3(3) #24