Walter Anderson
2013-Dec-06 15:44 UTC
[R] Need help figuring out sapply (and similar functions) with multiple parameter user defined function
I am having trouble understanding how to use sapply (or similar functions) with a user defined function with multiple parameters. I have the following functions defined q1.ans <- function(x) { retVal = 0 if (x == 1) { retVal = 1 } else if (x ==2) { retVal = 2 } return (retVal) } q2.ans <- function(x) { retVal = 0 if (x == 1) { retVal = 1 } else if (x ==2) { retVal = 3 } return (retVal) } q3.ans <- function(x) { retVal = 0 if (x == 1) { retVal = 2 } else if (x ==2) { retVal = 3 } return (retVal) } evaluate.questions <- function(q.1,q.2,q.3) { a <- q1.ans(q.1) b <- q2.ans(q.2) c <- q3.ans(q.3) retVal = 0 # Set default value to be no preference # The following code only implements those values from the state machine that show a preference (ID's 5,9,11,13-15,17-18,21,23-27) if (a == 0) { if (b == 1) { if (c == 1) { retVal = 1 # State machine ID 5 } } else if (b == 2) { if (c == 2) { retVal = 2 # State machine ID 9 } } } else if (a == 1) { if (b == 0) { if (c == 1) { retVal = 1 # State machine ID 11 } } else if (b == 1) { retVal = 1 # State machine ID's 13-15, value of C doesn't matter } else if (b == 2) { if (c == 1) { retVal = 1 # State machine ID 17 } else if (c == 2) { retVal = 2 # State machine ID 18 } } } else if (a == 2) { if (b == 0) { if (c == 2) { retVal = 2 # State machine ID 21 } } else if (b == 1) { if (c == 1) { retVal = 1 # State machine ID 23 } else if (c == 2) { retVal = 2 # State machine ID 24 } } else if (b == 2) { retVal = 2 # State machine ID's 25-27, value of C doesn't matter } } return (retVal) } And a data set that looks like this: ID,Q1,Q2,Q3 1,2,2,2 2,2,1,1 3,1,1,1 4,1,2,2 5,2,2,1 6,1,2,1 ... I have been researching and it appears that I should be using the sapply function to apply the evaluate.question function above to each row in the data frame like this preferences <- sapply(df, evaluate.questions, function(x,y,z) evaluate.questions(df['Q1'],df['Q2'],df['Q3'])) Unfortunately this doesn't work and the problem appears that the sapply function is not feeding the parameters to the evaluate.questions function as I expect. Can someone provide some guidance on what I am doing wrong? This is the error message I am getting: Error in x --1 : Comparison (1) is possible only for atomic and list types In addition: warning messages: In if (x == 1) { : the condition has length > 1 and only the first element will be used [[alternative HTML version deleted]]
PIKAL Petr
2013-Dec-06 15:59 UTC
[R] Need help figuring out sapply (and similar functions) with multiple parameter user defined function
Hi The warning is due to fact that "if" takes only single scalar value not an entire vector. Maybe you shall explain more clearly what result do you expect. I bet that there is vectorised solution to your problem but I am lost in your ifs and cannot follow what shall be the output. Please use dput(head(df)) when showing input data and clearly describe intended result. Regards Petr> -----Original Message----- > From: r-help-bounces at r-project.org [mailto:r-help-bounces at r- > project.org] On Behalf Of Walter Anderson > Sent: Friday, December 06, 2013 4:44 PM > To: r-help at r-project.org > Subject: [R] Need help figuring out sapply (and similar functions) with > multiple parameter user defined function > > I am having trouble understanding how to use sapply (or similar > functions) with a user defined function with multiple parameters. > > I have the following functions defined > > q1.ans <- function(x) > { > retVal = 0 > if (x == 1) { > retVal = 1 > } else if (x ==2) { > retVal = 2 > } > return (retVal) > } > q2.ans <- function(x) > { > retVal = 0 > if (x == 1) { > retVal = 1 > } else if (x ==2) { > retVal = 3 > } > return (retVal) > } > q3.ans <- function(x) > { > retVal = 0 > if (x == 1) { > retVal = 2 > } else if (x ==2) { > retVal = 3 > } > return (retVal) > } > > evaluate.questions <- function(q.1,q.2,q.3) > { > a <- q1.ans(q.1) > b <- q2.ans(q.2) > c <- q3.ans(q.3) > retVal = 0 # Set default value to be no preference > # The following code only implements those values from the state > machine that show a preference (ID's 5,9,11,13-15,17-18,21,23-27) > if (a == 0) { > if (b == 1) { > if (c == 1) { > retVal = 1 # State machine ID 5 > } > } else if (b == 2) { > if (c == 2) { > retVal = 2 # State machine ID 9 > } > } > } else if (a == 1) { > if (b == 0) { > if (c == 1) { > retVal = 1 # State machine ID 11 > } > } else if (b == 1) { > retVal = 1 # State machine ID's 13-15, value of C doesn't > matter > } else if (b == 2) { > if (c == 1) { > retVal = 1 # State machine ID 17 > } else if (c == 2) { > retVal = 2 # State machine ID 18 > } > } > } else if (a == 2) { > if (b == 0) { > if (c == 2) { > retVal = 2 # State machine ID 21 > } > } else if (b == 1) { > if (c == 1) { > retVal = 1 # State machine ID 23 > } else if (c == 2) { > retVal = 2 # State machine ID 24 > } > } else if (b == 2) { > retVal = 2 # State machine ID's 25-27, value of C doesn't > matter > } > } > return (retVal) > } > > And a data set that looks like this: > > ID,Q1,Q2,Q3 > 1,2,2,2 > 2,2,1,1 > 3,1,1,1 > 4,1,2,2 > 5,2,2,1 > 6,1,2,1 > ... > > > I have been researching and it appears that I should be using the > sapply function to apply the evaluate.question function above to each > row in the data frame like this > > preferences <- sapply(df, evaluate.questions, function(x,y,z) > evaluate.questions(df['Q1'],df['Q2'],df['Q3'])) > > Unfortunately this doesn't work and the problem appears that the sapply > function is not feeding the parameters to the evaluate.questions > function as I expect. Can someone provide some guidance on what I am > doing wrong? > > This is the error message I am getting: > > Error in x --1 : > Comparison (1) is possible only for atomic and list types In > addition: warning messages: > In if (x == 1) { : > the condition has length > 1 and only the first element will be used > > [[alternative HTML version deleted]] > > ______________________________________________ > R-help at r-project.org mailing list > https://stat.ethz.ch/mailman/listinfo/r-help > PLEASE do read the posting guide http://www.R-project.org/posting- > guide.html > and provide commented, minimal, self-contained, reproducible code.
William Dunlap
2013-Dec-06 16:43 UTC
[R] Need help figuring out sapply (and similar functions) with multiple parameter user defined function
> I have been researching and it appears that I should be using the sapply > function to apply the evaluate.question function above to each row in > the data frame like thisRead the documentation more closely: sapply(dataFrame, func) applies func() to each column, not row, of dataFrame.> preferences <- sapply(df, evaluate.questions, function(x,y,z) > evaluate.questions(df['Q1'],df['Q2'],df['Q3']))Furthermore, sapply(X = dataFrame, FUN = func, extraArgument) calls func(dataFrame[, i], extraArgument) for i in seq_len(ncol(dataFrame). One problem is that FUN=evaluate.questions takes 3 arguments and you give it only 2. Another problem is that the third argument you pass to sapply is a function (of 3 arguments) and FUN is not expecting any of its arguments to be functions. It may be easier for you to not use sapply here, but to use for-loops and come up with something that works. (Write tests that will indicate whether it works or not in a variety of situations.) Then transform it to use things like ifelse() and sapply() to make it more readable and run faster.> Unfortunately this doesn't work and the problem appears that the sapply > function is not feeding the parameters to the evaluate.questions > function as I expect. Can someone provide some guidance on what I am > doing wrong?Bill Dunlap Spotfire, TIBCO Software wdunlap tibco.com> -----Original Message----- > From: r-help-bounces at r-project.org [mailto:r-help-bounces at r-project.org] On Behalf > Of Walter Anderson > Sent: Friday, December 06, 2013 7:44 AM > To: r-help at r-project.org > Subject: [R] Need help figuring out sapply (and similar functions) with multiple parameter > user defined function > > I am having trouble understanding how to use sapply (or similar > functions) with a user defined function with multiple parameters. > > I have the following functions defined > > q1.ans <- function(x) > { > retVal = 0 > if (x == 1) { > retVal = 1 > } else if (x ==2) { > retVal = 2 > } > return (retVal) > } > q2.ans <- function(x) > { > retVal = 0 > if (x == 1) { > retVal = 1 > } else if (x ==2) { > retVal = 3 > } > return (retVal) > } > q3.ans <- function(x) > { > retVal = 0 > if (x == 1) { > retVal = 2 > } else if (x ==2) { > retVal = 3 > } > return (retVal) > } > > evaluate.questions <- function(q.1,q.2,q.3) > { > a <- q1.ans(q.1) > b <- q2.ans(q.2) > c <- q3.ans(q.3) > retVal = 0 # Set default value to be no preference > # The following code only implements those values from the state > # machine that show a preference (ID's 5,9,11,13-15,17-18,21,23-27) > if (a == 0) { > if (b == 1) { > if (c == 1) { > retVal = 1 # State machine ID 5 > } > } else if (b == 2) { > if (c == 2) { > retVal = 2 # State machine ID 9 > } > } > } else if (a == 1) { > if (b == 0) { > if (c == 1) { > retVal = 1 # State machine ID 11 > } > } else if (b == 1) { > retVal = 1 # State machine ID's 13-15, value of C doesn't matter > } else if (b == 2) { > if (c == 1) { > retVal = 1 # State machine ID 17 > } else if (c == 2) { > retVal = 2 # State machine ID 18 > } > } > } else if (a == 2) { > if (b == 0) { > if (c == 2) { > retVal = 2 # State machine ID 21 > } > } else if (b == 1) { > if (c == 1) { > retVal = 1 # State machine ID 23 > } else if (c == 2) { > retVal = 2 # State machine ID 24 > } > } else if (b == 2) { > retVal = 2 # State machine ID's 25-27, value of C doesn't matter > } > } > return (retVal) > } > > And a data set that looks like this: > > ID,Q1,Q2,Q3 > 1,2,2,2 > 2,2,1,1 > 3,1,1,1 > 4,1,2,2 > 5,2,2,1 > 6,1,2,1 > ... > > > I have been researching and it appears that I should be using the sapply > function to apply the evaluate.question function above to each row in > the data frame like this > > preferences <- sapply(df, evaluate.questions, function(x,y,z) > evaluate.questions(df['Q1'],df['Q2'],df['Q3'])) > > Unfortunately this doesn't work and the problem appears that the sapply > function is not feeding the parameters to the evaluate.questions > function as I expect. Can someone provide some guidance on what I am > doing wrong? > > This is the error message I am getting: > > Error in x --1 : > Comparison (1) is possible only for atomic and list types > In addition: warning messages: > In if (x == 1) { : > the condition has length > 1 and only the first element will be used > > [[alternative HTML version deleted]] > > ______________________________________________ > R-help at r-project.org mailing list > https://stat.ethz.ch/mailman/listinfo/r-help > PLEASE do read the posting guide http://www.R-project.org/posting-guide.html > and provide commented, minimal, self-contained, reproducible code.
PIKAL Petr
2013-Dec-09 15:23 UTC
[R] Need help figuring out sapply (and similar functions) with multiple parameter user defined function
Hi You probably missed this Instead of those tricky ifs (uff uff) you can use either of these df[df[,2]==2,2]<-3 df$C<-as.numeric(as.character(factor(df$C, labels=c(0,2,3)))) df A B C 1 0 3 3 2 0 1 2 3 0 3 2 4 1 0 3 5 1 0 3 6 2 3 2 7 1 3 2 8 2 3 3 9 1 1 0 10 0 0 3 And here I am lost again. Please, can you ***clearly*** state the way how do you want to choose preferences based on values in those three columns? Regards Petr Petr Pikal From: Walter Anderson [mailto:wandrson01@gmail.com] Sent: Friday, December 06, 2013 5:32 PM To: PIKAL Petr Subject: RE: [R] Need help figuring out sapply (and similar functions) with multiple parameter user defined function I posted the first 6 rows of my data in the first post. On Dec 6, 2013 10:31 AM, "PIKAL Petr" <petr.pikal@precheza.cz<mailto:petr.pikal@precheza.cz>> wrote: Hi So first step is over. Anyway, is there any problem with using dput as I suggested? Instead of using your date I need to generate my own. A<-sample(0:2, 10, replace=T) B<-sample(0:2, 10, replace=T) C<-sample(0:2, 10, replace=T) df<-data.frame(A,B,C) df[df[,2]==2,2]<-3 df$C<-as.numeric(as.character(factor(df$C, labels=c(0,2,3)))) df A B C 1 0 3 3 2 0 1 2 3 0 3 2 4 1 0 3 5 1 0 3 6 2 3 2 7 1 3 2 8 2 3 3 9 1 1 0 10 0 0 3> -----Original Message----- > From: Walter Anderson [mailto:wandrson01@gmail.com<mailto:wandrson01@gmail.com>] > Sent: Friday, December 06, 2013 5:11 PM > To: PIKAL Petr; r-help@r-project.org<mailto:r-help@r-project.org> > Subject: Re: [R] Need help figuring out sapply (and similar functions) > with multiple parameter user defined function > > Thank you for your response! > > I am attempting to determine a preference from the answers to three > binomial questions; > > q.1) 1 or 2 q.2) 1 or 3 q.3) 2 or 3 > > However, the questions are coded with either a 1 or 2 (though no answer > is also possible) and the first three functions (q#.ans) convert those > values to the 1,2,or 3 shown aboveInstead of those tricky ifs (uff uff) you can use either of these df[df[,2]==2,2]<-3 df$C<-as.numeric(as.character(factor(df$C, labels=c(0,2,3)))) df A B C 1 0 3 3 2 0 1 2 3 0 3 2 4 1 0 3 5 1 0 3 6 2 3 2 7 1 3 2 8 2 3 3 9 1 1 0 10 0 0 3 And here I am lost again. Please, can you clearly state the way how do you want to choose preferences based on values in those three columns. Regards Petr> > and generate one of the following result for each row of the table; 0 - > no preference, or 1,2,3 which indicates the preference indicated by the > question > > The if's implement the following state conditions: > > # ID A B C Preference > # 1 0 0 0 None > # 2 0 0 1 None > # 3 0 0 2 None > # 4 0 1 0 None > # 5 0 1 1 Option 1 > # 6 0 1 2 None > # 7 0 2 0 None > # 8 0 2 1 None > # 9 0 2 2 Option 2 > # 10 1 0 0 None > # 11 1 0 1 Option 1 > # 12 1 0 2 None > # 13 1 1 0 Option 1 > # 14 1 1 1 Option 1 > # 15 1 1 2 Option 1 > # 16 1 2 0 None > # 17 1 2 1 Option 1 > # 18 1 2 2 Option 2 > # 19 2 0 0 None > # 20 2 0 1 None > # 21 2 0 2 Option 2 > # 22 2 1 0 None > # 23 2 1 1 Option 1 > # 24 2 1 2 Option 2 > # 25 2 2 0 Option 2 > # 26 2 2 1 Option 2 > # 27 2 2 2 Option 2 > > The if statement only implements those values from the state machine > that show a preference (ID's 5,9,11,13-15,17-18,21,23-27) > > On 12/06/2013 09:59 AM, PIKAL Petr wrote: > > Hi > > > > The warning is due to fact that "if" takes only single scalar value > not an entire vector. > > > > Maybe you shall explain more clearly what result do you expect. > > > > I bet that there is vectorised solution to your problem but I am lost > in your ifs and cannot follow what shall be the output. > > > > Please use > > > > dput(head(df)) > > > > when showing input data and clearly describe intended result. > > > > Regards > > Petr > > > > > >> -----Original Message----- > >> From: r-help-bounces@r-project.org<mailto:r-help-bounces@r-project.org> [mailto:r-help-bounces@r-<mailto:r-help-bounces@r-> > >> project.org<http://project.org>] On Behalf Of Walter Anderson > >> Sent: Friday, December 06, 2013 4:44 PM > >> To: r-help@r-project.org<mailto:r-help@r-project.org> > >> Subject: [R] Need help figuring out sapply (and similar functions) > >> with multiple parameter user defined function > >> > >> I am having trouble understanding how to use sapply (or similar > >> functions) with a user defined function with multiple parameters. > >> > >> I have the following functions defined > >> > >> q1.ans <- function(x) > >> { > >> retVal = 0 > >> if (x == 1) { > >> retVal = 1 > >> } else if (x ==2) { > >> retVal = 2 > >> } > >> return (retVal) > >> } > >> q2.ans <- function(x) > >> { > >> retVal = 0 > >> if (x == 1) { > >> retVal = 1 > >> } else if (x ==2) { > >> retVal = 3 > >> } > >> return (retVal) > >> } > >> q3.ans <- function(x) > >> { > >> retVal = 0 > >> if (x == 1) { > >> retVal = 2 > >> } else if (x ==2) { > >> retVal = 3 > >> } > >> return (retVal) > >> } > >> > >> evaluate.questions <- function(q.1,q.2,q.3) > >> { > >> a <- q1.ans(q.1) > >> b <- q2.ans(q.2) > >> c <- q3.ans(q.3) > >> retVal = 0 # Set default value to be no preference > >> # The following code only implements those values from the > state > >> machine that show a preference (ID's 5,9,11,13-15,17-18,21,23- > 27) > >> if (a == 0) { > >> if (b == 1) { > >> if (c == 1) { > >> retVal = 1 # State machine ID 5 > >> } > >> } else if (b == 2) { > >> if (c == 2) { > >> retVal = 2 # State machine ID 9 > >> } > >> } > >> } else if (a == 1) { > >> if (b == 0) { > >> if (c == 1) { > >> retVal = 1 # State machine ID 11 > >> } > >> } else if (b == 1) { > >> retVal = 1 # State machine ID's 13-15, value of C > doesn't > >> matter > >> } else if (b == 2) { > >> if (c == 1) { > >> retVal = 1 # State machine ID 17 > >> } else if (c == 2) { > >> retVal = 2 # State machine ID 18 > >> } > >> } > >> } else if (a == 2) { > >> if (b == 0) { > >> if (c == 2) { > >> retVal = 2 # State machine ID 21 > >> } > >> } else if (b == 1) { > >> if (c == 1) { > >> retVal = 1 # State machine ID 23 > >> } else if (c == 2) { > >> retVal = 2 # State machine ID 24 > >> } > >> } else if (b == 2) { > >> retVal = 2 # State machine ID's 25-27, value of C > doesn't > >> matter > >> } > >> } > >> return (retVal) > >> } > >> > >> And a data set that looks like this: > >> > >> ID,Q1,Q2,Q3 > >> 1,2,2,2 > >> 2,2,1,1 > >> 3,1,1,1 > >> 4,1,2,2 > >> 5,2,2,1 > >> 6,1,2,1 > >> ... > >> > >> > >> I have been researching and it appears that I should be using the > >> sapply function to apply the evaluate.question function above to > each > >> row in the data frame like this > >> > >> preferences <- sapply(df, evaluate.questions, function(x,y,z) > >> evaluate.questions(df['Q1'],df['Q2'],df['Q3'])) > >> > >> Unfortunately this doesn't work and the problem appears that the > >> sapply function is not feeding the parameters to the > >> evaluate.questions function as I expect. Can someone provide some > >> guidance on what I am doing wrong? > >> > >> This is the error message I am getting: > >> > >> Error in x --1 : > >> Comparison (1) is possible only for atomic and list types In > >> addition: warning messages: > >> In if (x == 1) { : > >> the condition has length > 1 and only the first element will be > >> used > >> > >> [[alternative HTML version deleted]] > >> > >> ______________________________________________ > >> R-help@r-project.org<mailto:R-help@r-project.org> mailing list > >> https://stat.ethz.ch/mailman/listinfo/r-help > >> PLEASE do read the posting guide http://www.R-project.org/posting- > >> guide.html and provide commented, minimal, self-contained, > >> reproducible code.[[alternative HTML version deleted]]
PIKAL Petr
2013-Dec-09 16:21 UTC
[R] Need help figuring out sapply (and similar functions) with multiple parameter user defined function
Hi you are still rather cryptic. If you said you want to extract prevalent choices in each row it would save me (and you) a lot of time. Import data and make necessary chnages survey.results <- read.csv("SamplePairedComparisonData.csv") survey.results[survey.results[,3]==2,3]<-3 # Convert column 3 (Q2) to a value of 3 if the existing value is 2 # The order of the following two commands is important, don't change survey.results[survey.results[,4]==2,4]<-3 # Convert column 4 (Q3) to a value of 3 if the existing value is 1 survey.results[survey.results[,4]==1,4]<-2 # Convert column 4 (Q4) to a value of 2 if the existing value is 1 survey.results$Q1 <- factor(survey.results$Q1, labels=c("None","Option 1","Option 2")) survey.results$Q2 <- factor(survey.results$Q2, labels=c("None","Option 1","Option 3")) survey.results$Q3 <- factor(survey.results$Q3, labels=c("None","Option 2","Option 3")) Then make the object matrix without first column sr<-survey.results[,-1] sr<-as.matrix(sr) Elaborate evaluation function fff <- function(x) names(which.max(table(x))) Apply function to matrix result <- apply(sr,1, fff) Bind result with original data survey.results <- cbind(survey.results, result) And voila, you shall have reqiured values. Regards Petr From: Walter Anderson [mailto:wandrson01@gmail.com] Sent: Monday, December 09, 2013 4:37 PM To: PIKAL Petr Subject: Re: [R] Need help figuring out sapply (and similar functions) with multiple parameter user defined function Peter. First, let me thank you for your assistance on this. Your ideas below for eliminating the three functions I had that 'adjusted' the data was received and appreciated. I included that approach in my revised script. I am only left with a for loop and my final preference determining code. I am including the current script and test data (all possible choices included-27).>From my review of all of the responses, I don't see an alternative to the if then block that tests the state of the three questions or the for loop that executes it. I made some attempts to use the ifelse statement mentioned in the responses, but couldn't get anything to work.Again, thanks for your assistance and time on this! Walter On 12/09/2013 09:23 AM, PIKAL Petr wrote: Hi You probably missed this Instead of those tricky ifs (uff uff) you can use either of these df[df[,2]==2,2]<-3 df$C<-as.numeric(as.character(factor(df$C, labels=c(0,2,3)))) df A B C 1 0 3 3 2 0 1 2 3 0 3 2 4 1 0 3 5 1 0 3 6 2 3 2 7 1 3 2 8 2 3 3 9 1 1 0 10 0 0 3 And here I am lost again. Please, can you ***clearly*** state the way how do you want to choose preferences based on values in those three columns? Regards Petr Petr Pikal From: Walter Anderson [mailto:wandrson01@gmail.com] Sent: Friday, December 06, 2013 5:32 PM To: PIKAL Petr Subject: RE: [R] Need help figuring out sapply (and similar functions) with multiple parameter user defined function I posted the first 6 rows of my data in the first post. On Dec 6, 2013 10:31 AM, "PIKAL Petr" <petr.pikal@precheza.cz<mailto:petr.pikal@precheza.cz>> wrote: Hi So first step is over. Anyway, is there any problem with using dput as I suggested? Instead of using your date I need to generate my own. A<-sample(0:2, 10, replace=T) B<-sample(0:2, 10, replace=T) C<-sample(0:2, 10, replace=T) df<-data.frame(A,B,C) df[df[,2]==2,2]<-3 df$C<-as.numeric(as.character(factor(df$C, labels=c(0,2,3)))) df A B C 1 0 3 3 2 0 1 2 3 0 3 2 4 1 0 3 5 1 0 3 6 2 3 2 7 1 3 2 8 2 3 3 9 1 1 0 10 0 0 3> -----Original Message----- > From: Walter Anderson [mailto:wandrson01@gmail.com<mailto:wandrson01@gmail.com>] > Sent: Friday, December 06, 2013 5:11 PM > To: PIKAL Petr; r-help@r-project.org<mailto:r-help@r-project.org> > Subject: Re: [R] Need help figuring out sapply (and similar functions) > with multiple parameter user defined function > > Thank you for your response! > > I am attempting to determine a preference from the answers to three > binomial questions; > > q.1) 1 or 2 q.2) 1 or 3 q.3) 2 or 3 > > However, the questions are coded with either a 1 or 2 (though no answer > is also possible) and the first three functions (q#.ans) convert those > values to the 1,2,or 3 shown aboveInstead of those tricky ifs (uff uff) you can use either of these df[df[,2]==2,2]<-3 df$C<-as.numeric(as.character(factor(df$C, labels=c(0,2,3)))) df A B C 1 0 3 3 2 0 1 2 3 0 3 2 4 1 0 3 5 1 0 3 6 2 3 2 7 1 3 2 8 2 3 3 9 1 1 0 10 0 0 3 And here I am lost again. Please, can you clearly state the way how do you want to choose preferences based on values in those three columns. Regards Petr> > and generate one of the following result for each row of the table; 0 - > no preference, or 1,2,3 which indicates the preference indicated by the > question > > The if's implement the following state conditions: > > # ID A B C Preference > # 1 0 0 0 None > # 2 0 0 1 None > # 3 0 0 2 None > # 4 0 1 0 None > # 5 0 1 1 Option 1 > # 6 0 1 2 None > # 7 0 2 0 None > # 8 0 2 1 None > # 9 0 2 2 Option 2 > # 10 1 0 0 None > # 11 1 0 1 Option 1 > # 12 1 0 2 None > # 13 1 1 0 Option 1 > # 14 1 1 1 Option 1 > # 15 1 1 2 Option 1 > # 16 1 2 0 None > # 17 1 2 1 Option 1 > # 18 1 2 2 Option 2 > # 19 2 0 0 None > # 20 2 0 1 None > # 21 2 0 2 Option 2 > # 22 2 1 0 None > # 23 2 1 1 Option 1 > # 24 2 1 2 Option 2 > # 25 2 2 0 Option 2 > # 26 2 2 1 Option 2 > # 27 2 2 2 Option 2 > > The if statement only implements those values from the state machine > that show a preference (ID's 5,9,11,13-15,17-18,21,23-27) > > On 12/06/2013 09:59 AM, PIKAL Petr wrote: > > Hi > > > > The warning is due to fact that "if" takes only single scalar value > not an entire vector. > > > > Maybe you shall explain more clearly what result do you expect. > > > > I bet that there is vectorised solution to your problem but I am lost > in your ifs and cannot follow what shall be the output. > > > > Please use > > > > dput(head(df)) > > > > when showing input data and clearly describe intended result. > > > > Regards > > Petr > > > > > >> -----Original Message----- > >> From: r-help-bounces@r-project.org<mailto:r-help-bounces@r-project.org> [mailto:r-help-bounces@r-<mailto:r-help-bounces@r-> > >> project.org<http://project.org>] On Behalf Of Walter Anderson > >> Sent: Friday, December 06, 2013 4:44 PM > >> To: r-help@r-project.org<mailto:r-help@r-project.org> > >> Subject: [R] Need help figuring out sapply (and similar functions) > >> with multiple parameter user defined function > >> > >> I am having trouble understanding how to use sapply (or similar > >> functions) with a user defined function with multiple parameters. > >> > >> I have the following functions defined > >> > >> q1.ans <- function(x) > >> { > >> retVal = 0 > >> if (x == 1) { > >> retVal = 1 > >> } else if (x ==2) { > >> retVal = 2 > >> } > >> return (retVal) > >> } > >> q2.ans <- function(x) > >> { > >> retVal = 0 > >> if (x == 1) { > >> retVal = 1 > >> } else if (x ==2) { > >> retVal = 3 > >> } > >> return (retVal) > >> } > >> q3.ans <- function(x) > >> { > >> retVal = 0 > >> if (x == 1) { > >> retVal = 2 > >> } else if (x ==2) { > >> retVal = 3 > >> } > >> return (retVal) > >> } > >> > >> evaluate.questions <- function(q.1,q.2,q.3) > >> { > >> a <- q1.ans(q.1) > >> b <- q2.ans(q.2) > >> c <- q3.ans(q.3) > >> retVal = 0 # Set default value to be no preference > >> # The following code only implements those values from the > state > >> machine that show a preference (ID's 5,9,11,13-15,17-18,21,23- > 27) > >> if (a == 0) { > >> if (b == 1) { > >> if (c == 1) { > >> retVal = 1 # State machine ID 5 > >> } > >> } else if (b == 2) { > >> if (c == 2) { > >> retVal = 2 # State machine ID 9 > >> } > >> } > >> } else if (a == 1) { > >> if (b == 0) { > >> if (c == 1) { > >> retVal = 1 # State machine ID 11 > >> } > >> } else if (b == 1) { > >> retVal = 1 # State machine ID's 13-15, value of C > doesn't > >> matter > >> } else if (b == 2) { > >> if (c == 1) { > >> retVal = 1 # State machine ID 17 > >> } else if (c == 2) { > >> retVal = 2 # State machine ID 18 > >> } > >> } > >> } else if (a == 2) { > >> if (b == 0) { > >> if (c == 2) { > >> retVal = 2 # State machine ID 21 > >> } > >> } else if (b == 1) { > >> if (c == 1) { > >> retVal = 1 # State machine ID 23 > >> } else if (c == 2) { > >> retVal = 2 # State machine ID 24 > >> } > >> } else if (b == 2) { > >> retVal = 2 # State machine ID's 25-27, value of C > doesn't > >> matter > >> } > >> } > >> return (retVal) > >> } > >> > >> And a data set that looks like this: > >> > >> ID,Q1,Q2,Q3 > >> 1,2,2,2 > >> 2,2,1,1 > >> 3,1,1,1 > >> 4,1,2,2 > >> 5,2,2,1 > >> 6,1,2,1 > >> ... > >> > >> > >> I have been researching and it appears that I should be using the > >> sapply function to apply the evaluate.question function above to > each > >> row in the data frame like this > >> > >> preferences <- sapply(df, evaluate.questions, function(x,y,z) > >> evaluate.questions(df['Q1'],df['Q2'],df['Q3'])) > >> > >> Unfortunately this doesn't work and the problem appears that the > >> sapply function is not feeding the parameters to the > >> evaluate.questions function as I expect. Can someone provide some > >> guidance on what I am doing wrong? > >> > >> This is the error message I am getting: > >> > >> Error in x --1 : > >> Comparison (1) is possible only for atomic and list types In > >> addition: warning messages: > >> In if (x == 1) { : > >> the condition has length > 1 and only the first element will be > >> used > >> > >> [[alternative HTML version deleted]] > >> > >> ______________________________________________ > >> R-help@r-project.org<mailto:R-help@r-project.org> mailing list > >> https://stat.ethz.ch/mailman/listinfo/r-help > >> PLEASE do read the posting guide http://www.R-project.org/posting- > >> guide.html and provide commented, minimal, self-contained, > >> reproducible code.[[alternative HTML version deleted]]
Walter Anderson
2013-Dec-09 20:40 UTC
[R] Need help figuring out sapply (and similar functions) with multiple parameter user defined function
Karen, Thank you for your reply. That approach makes the code for determining preference much clearer. Unfortunately, it appears I am still needing to use a for loop to process each row. For any who find these posts and may have similar questions, I am including my current code and sample data to provide a working solution: survey.results <- read.csv("SamplePairedComparisonData.csv") # The following function evaluates which, if any, preference the respondent has shown get.pref <- function(x) { # names(which.max(table(x))) n.1 <- sum(x==1) # Calculate the number of times the respondent chose option 1 n.2 <- sum(x==2) # Calculate the number of times the respondent chose option 2 n.3 <- sum(x==3) # Calculate the number of times the respondent chose option 3 retVal <- "None" if (n.1 >= 2) { retVal <- "Option 1" } else if (n.2 >= 2) { retVal <- "Option 2" } else if (n.3 >= 2) { retVal <- "Option 3" } return(retVal) } # The data is expected to be organized as so: # ID, Q1, Q2, Q3 # and that the questions are in the following format # Q.1) Which do you prefer? # 1) Option 1 # 2) Option 2 # Q.2) Which do you prefer? # 1) Option 1 # 2) Option 3 # Q.3) Which do you prefer? # 1) Option 2 # 2) Option 3 # And the next three lines reprocess the data table to organize the questions so that the values for Q.2) are 1 or 3 and the values for Q.3) are 2 or 3 survey.results[survey.results[,3]==2,3]<-3 # Convert column 3 (Q2) to a value of 3 if the existing value is 2 # The order of the following two commands is important, don't change survey.results[survey.results[,4]==2,4]<-3 # Convert column 4 (Q3) to a value of 3 if the existing value is 1 survey.results[survey.results[,4]==1,4]<-2 # Convert column 4 (Q3) to a value of 2 if the existing value is 1 for (indx in 1:length(survey.results$ID)) { survey.results$Preference[indx] <- get.pref(survey.results[indx, 2:4]) } # The following lines convert the numerical values in the fields to text (factors) # If the questions don't have empty (zero) values than the "None" should be removed from those questions where zero isn't possible survey.results$Q1 <- factor(survey.results$Q1, labels=c("None","Option 1","Option 2")) survey.results$Q2 <- factor(survey.results$Q2, labels=c("None","Option 1","Option 3")) survey.results$Q3 <- factor(survey.results$Q3, labels=c("None","Option 2","Option 3")) # survey.results$Preference <- apply(as.matrix(survey.results[,-1]),1,get.pref) and here is the sample data. #The following sample data represents every possible response to the three questions of the type described above ID,Q1,Q2,Q3 1,0,0,0 2,0,0,1 3,0,0,2 4,0,1,0 5,0,1,1 6,0,1,2 7,0,2,0 8,0,2,1 9,0,2,2 10,1,0,0 11,1,0,1 12,1,0,2 13,1,1,0 14,1,1,1 15,1,1,2 16,1,2,0 17,1,2,1 18,1,2,2 19,2,0,0 20,2,0,1 21,2,0,2 22,2,1,0 23,2,1,1 24,2,1,2 25,2,2,0 26,2,2,1 27,2,2,2 On 12/09/2013 09:42 AM, Karen Keating wrote:> Hi Walter, > From your list of preferences, it seems that Option 2 is preferred if > there are at least two 2's for the ID, and Option 1 is preferred if > there are at least two 1's for the ID. If neither of these conditions > are met, then there is no preference. If this interpretation is > correct, I would suggest replacing your list of 'if' statements with > the following: > > get.pref<-function(x) { > n.1<-sum(x==1) > n.2<-sum(x==2) > pref='None' > if(n.1>=2) {pref='Option 1'} else > if(n.2>=2) {pref='Option 2'} > pref > } > R-help@r-project.org <mailto:R-help@r-project.org> mailing list > https://stat.ethz.ch/mailman/listinfo/r-help > PLEASE do read the posting guide > http://www.R-project.org/posting-guide.html > and provide commented, minimal, self-contained, reproducible code. >[[alternative HTML version deleted]]