2012-06-06 60 views
2

其他環路我的條件和coformula一個表:替代的號碼,如果r中

MTR     CLD      AF     PI 
AA     AA      AB     0.5/a  (cond1) 
AA     AB      AB     0.5/a  (cond2) 
AB     AA      AB     0.5 /a  (cond3) 
AA     AA      AA     1/a (cond4) 
AB     AA      AA      1/a (cond5) 
BB     AB      AA     1/a (cond6) 
AB     AB      AA     1/(a+b) (cond7) 
AB     AB      AB     1/(a+b) (cond8) 

如果沒有條件匹配應該產生「NA」。

# table of conditions 
MTR <- c("AA", "AA", "AB", "AA", "AB", "BB", "AB", "AB") 
CLD <- c("AA", "AB", "AA", "AA", "AA", "AB", "AB", "AB") 
AF <- c("AB", "AB", "AB", "AA", "AA", "AA", "AA", "AB") 
PI <- c("0.5/a", "0.5/a", "0.5/a", "1/a", "1/a", "1/a", 
     "1/(a+b)", "1/(a+b)") 

這裏有兩個數據集的應用:

# the dataset to be applied to 
dataf <- data.frame (MTR = c("AB", "BB", "AB", "BB", "AB", "AA"), 
        CLD= c("AA", "AB", "AA", "AB", "AB", "AB"), 
        AF = c("AA", "AB", "BB", "AB", "BB", "AB") 
        ) 


    MTR CLD AF 
1 AB AA AA 
2 BB AB AB 
3 AB AA BB 
4 BB AB AB 
5 AB AB BB 
6 AA AB AB 

a = c(0.5, 0.4, 0.3, 0.5, 0.2, 0.4) 
mapd <- data.frame(a = a, b = 1-a) 

編輯:下面的建議下,我可以在這兩個dataframes合而爲一: newdf < - data.frame(DATAF,MAPD)

MTR CLD AF a b 
1 AB AA AA 0.5 0.5 
2 BB AB AB 0.4 0.6 
3 AB AA BB 0.3 0.7 
4 BB AB AB 0.5 0.5 
5 AB AB BB 0.2 0.8 
6 AA AB AB 0.4 0.6 

我認爲我可以通過創建的if else解決這個問題 - 但也有很多條件,我不知道,這僅僅是(很好)辦法的事情。

PI = NULL 
if (dataf$MTR = "AA", dataf$CLD = "AA", dataf$AF = "AB") { 
          PI = 0.5/mapd$a } else { 
    if (dataf$MTR = "AA", dataf$CLD = "AB", dataf$AF = "AB"){ 
          PI = 0.5/mapd$a 
          } else { 
     ............. so on 

有沒有其他辦法呢?

+0

可以看看向量化的'ifelse()','switch()'也許對你有好處。 – Chase

+0

你的測試'dataf對象有很多行,沒有可能匹配你的條件表和coformulae表。 –

+0

@DWin謝謝,我忘記提及,如果沒有匹配,NA將被輸出...最後的其他條件 – SHRram

回答

3

看起來過於複雜!

我的建議是將條件表製成一個三列的數據框:第一列是MTR,CLD和AF列的粘貼(所以一個典型的條目可能是「AB〜AA〜 AB「),其他兩列將被稱爲COEFA和COEFAB,它們是PI表達式中的係數乘以1/a和係數乘以1 /(a + b)...例如「0.5/a」將具有COEFA = 0.5和COEFAB = 0,而「1 /(a + b)」將具有COEFA = 0並且COEFB = 1。

要清楚,條件1將以表格MTR_CLD_AF =「AA〜AA〜AB」,COEFA = 0.5,COEFB = 0。

然後爲了確定哪個條件適合dataf中的每一行,你只需要粘貼MTR,CLD和AF,直至條件數據幀中的列MTR_CLD_AF,從而提取該行的COEFA和COEFB。然後,您的PI變量的期望值爲COEFA *(1/a)+ COEFB *(1 /(a + b))。

讓我知道,如果進一步的解釋或代碼將是有益的:)

追問:

下面是在代碼中的刺我在這裏使用:

### first, all your object definitions... 

MTR <- c("AA", "AA", "AB", "AA", "AB", "BB", "AB", "AB") 
CLD <- c("AA", "AB", "AA", "AA", "AA", "AB", "AB", "AB") 
AF <- c("AB", "AB", "AB", "AA", "AA", "AA", "AA", "AB") 
PI <- c("0.5/a", "0.5/a", "0.5/a", "1/a", "1/a", "1/a", 
     "1/(a+b)", "1/(a+b)") 

dataf <- data.frame (MTR = c("AB", "BB", "AB", "BB", "AB", "AA"), 
        CLD= c("AA", "AB", "AA", "AB", "AB", "AB"), 
        AF = c("AA", "AB", "BB", "AB", "BB", "AB") 
        ) 
a = c(0.5, 0.4, 0.3, 0.5, 0.2, 0.4) 
mapd <- data.frame(a = a, b = 1-a) 

### first create COEFA and COEFAB from PI (could automate but small 
### enough to do manually here) 

COEFA <- c(0.5, 0.5, 0.5, 1, 1, 1, 0, 0) 
COEFAB <- c(0, 0, 0, 0, 0, 0, 1, 1) 

### then create conditions data frame as specified in my solution 

cond = data.frame(MTR_CLD_AF = paste(MTR,CLD,AF,sep="~"), COEFA, COEFAB, 
        stringsAsFactors=FALSE) 

### now put all the data in dataf and mapd into one object alldata to 
### keep things neat 

alldata = data.frame(MTR = dataf$MTR, CLD = dataf$CLD, AF = dataf$AF, 
        a = mapd$a, b=mapd$b, stringsAsFactors=FALSE) 

### now go ahead and get COEFA and COEFB for each row in alldata - first 
### do the match up (look in matcond to see this) then copy coef columns 
### over to alldata 

matcond=cond[match(with(alldata, paste(MTR, CLD, AF, sep="~")), 
        cond$MTR_CLD_AF),] 
alldata$COEFA = matcond$COEFA 
alldata$COEFAB = matcond$COEFAB 

### finally compute COEFA*(1/a) + COEFAB*(1/(a+b)) using the columns of 
### alldata, and store the answer in column called PI 

alldata$PI = with(alldata, COEFA*(1/a) + COEFAB*(1/(a+b))) 

### that's it! as noted elsewhere, the value will be NA if no matching 
### condition exists 
+0

感謝您的意見。我做了一些更改,代碼會有所幫助 – SHRram

+1

請參閱http://stackoverflow.com/a/9214837/210673上的非常類似答案的代碼 – Aaron

+0

我將在我的答案結尾添加代碼作爲「跟進」 :) –

2
#data.frame with conditions and functions  
confun<-data.frame(c1=c("AA","AA","AB"), 
         c2=c("AA","AB","AA"), 
         c3=c("AB","AB","AB"), 
         fun=c("0.5/a","0.5/b","1/(a+b)")) 
confun$fun<-as.character(confun$fun) 

confun 
     c1 c2 c3  fun 
    1 AA AA AB 0.5/a 
    2 AA AB AB 0.5/b 
    3 AB AA AB 1/(a+b) 

#data   
test<-data.frame(c1=c("AA","AB"),c2=c("AB","AA"),c3=c("AB","AB"),a=c(2,3)) 
    test$b<-1-test$a 

test 
    c1 c2 c3 a b 
1 AA AB AB 2 -1 
2 AB AA AB 3 -2 

fun<-function(c1,c2,c3) as.numeric(rownames(confun[paste(confun$c1,confun$c2,confun$c3)==paste(c1,c2,c3),]))  
test$i<-mapply(fun,test$c1,test$c2,test$c3) 

fun2<-function(a,b,i) eval(parse(text=confun$fun[i])) 

res<-mapply(fun2,test$a,test$b,test$i) 

res 
[1] -0.5 1.0 

快速&髒

+0

我很驚訝重訪這個答案,並找到downvote。我已經施加了有限的權重,可以糾正這種不公正。這似乎是敏感和準確的。 –

+0

我非常感謝。我一直在思考代碼是否有嚴重錯誤。 – Roland

+0

@羅蘭我會給你+1的努力來幫助我,並糾正不公正 – SHRram