Bert Gunter
2021-Jun-05 19:26 UTC
[R] Beginner problem - using mod function to print odd numbers
I'm sorry, but this is a good example of how one should *not* do this in R. I also should apologize for any pedantry that follows, but I believe this serves as a nice example of the ideas. Two of R's central features as a "data science" language are that many of its core capabilities are "vectorized" -- can calculate on whole objects (at the user-visible interpreter level) rather than requiring explicit loops; and that it can use object indexing in several different modalities, here logical indexing, for extraction and replacement in whole objects such as vectors and matrices. Not only does this typically yield simpler, more readable code (admittedly, a subjective judgment), but it is also typically much faster, though I grant you that this can often be overrated. In this instance, the several lines of looping code you presented can be condensed into a single line:> span <- 1:20 > span[span %% 2 == 1][1] 1 3 5 7 9 11 13 15 17 19 ### Trickier, but perhaps instructive, is: ###> span[TRUE & span %% 2][1] 1 3 5 7 9 11 13 15 17 19 All languages trade off various strengths and weaknesses, but I think it's fair to say that one should try to work within the paradigms that are the language's strengths when possible, R's vectorization and indexing in this example. Cheers, Bert Gunter "The trouble with having an open mind is that people keep coming along and sticking things into it." -- Opus (aka Berkeley Breathed in his "Bloom County" comic strip ) On Sat, Jun 5, 2021 at 11:05 AM William Michels via R-help < r-help at r-project.org> wrote:> > i <- 1L; span <- 1:100; result <- NA; > > for (i in span){ > + ifelse(i %% 2 != 0, result[i] <- TRUE, result[i] <- FALSE) > + } > > span[result] > [1] 1 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31 33 35 37 39 41 43 > 45 47 49 51 53 55 57 > [30] 59 61 63 65 67 69 71 73 75 77 79 81 83 85 87 89 91 93 95 97 99 > > > > HTH, Bill. > > W. Michels, Ph.D. > > > On Sat, Jun 5, 2021 at 12:55 AM Stefan Evert <stefanML at collocations.de> > wrote: > > > > > > > > I don't understand. -- > > > > > > 7%%2=1 > > > 9%%2=1 > > > 11%%2=1 > > > > > > What aren't these numbers printing ? > > > > > > num<-0 > > > for (i in 1:100){ > > > num<-num+i > > > if (num%%2 != 0) > > > print(num) > > > } > > > > Your code tests the numbers > > > > 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 66, ? > > > > and correctly prints the odd ones among them. > > > > But I suppose that's not what you wanted to do? > > > > ______________________________________________ > > R-help at r-project.org mailing list -- To UNSUBSCRIBE and more, see > > 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. > > ______________________________________________ > R-help at r-project.org mailing list -- To UNSUBSCRIBE and more, see > 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]]
William Michels
2021-Jun-06 11:34 UTC
[R] Beginner problem - using mod function to print odd numbers
Dear Bert, First off, I want to thank you for the many hundreds (if not thousands) of excellent posts I've read from you on this mailing list over the years. And you are absolutely correct that when using the `%%` modulo operator, your code is the most compact and the most idiomatic. That being said, if someone coming from another programming language is posting code on this mailing list using a `for()` loop, they may be most comfortable getting working code back from this mailing-list that still uses a `for()` loop in R. Furthermore, people often start by *filtering* their data, when a better approach might be to first *recode* it, for which the `ifelse()` function provides a nice solution. But of course, a more simple approach than I previously posted would be below (although less idiomatic than your answer):> object <- 1:100 > index <- ifelse(object %% 2 == 1, TRUE, FALSE) > object[index][1] 1 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31 33 35 37 39 41 43 45 47 49 51 53 55 57 [30] 59 61 63 65 67 69 71 73 75 77 79 81 83 85 87 89 91 93 95 97 99>This brings us to the question of programming 'philosophy': certain languages advise "TMTOWTDI", while another advises "There should be one--and preferably only one--obvious way to do it." Where does R fit on this spectrum? I believe one of R's underappreciated strengths is being more in-line with the "TMTOWTDI" principle. So people coming from other languages can get good results right off the bat using vectorized indexing/filtering, or for() loops, or the apply() family of functions, or writing a custom function (all answers given in this thread). Finally, if a nascent R programmer ever ventures into filtering their data using objects and indexes of different lengths, they should have a grasp of the code examples below (recycling rule): long_vec <- 1:16 print(long_vec) short_vec <- rep(4,8) print(short_vec) print(long_vec[long_vec > short_vec]) span <- 1:length(short_vec) print(long_vec[span][long_vec[span] > short_vec]) print(long_vec[span][long_vec > short_vec]) Best Regards, Bill. W. Michels, Ph.D. On Sat, Jun 5, 2021 at 12:26 PM Bert Gunter <bgunter.4567 at gmail.com> wrote:> > I'm sorry, but this is a good example of how one should *not* do this in R. I also should apologize for any pedantry that follows, but I believe this serves as a nice example of the ideas. > > Two of R's central features as a "data science" language are that many of its core capabilities are "vectorized" -- can calculate on whole objects (at the user-visible interpreter level) rather than requiring explicit loops; and that it can use object indexing in several different modalities, here logical indexing, for extraction and replacement in whole objects such as vectors and matrices. Not only does this typically yield simpler, more readable code (admittedly, a subjective judgment), but it is also typically much faster, though I grant you that this can often be overrated. > > In this instance, the several lines of looping code you presented can be condensed into a single line: > > > span <- 1:20 > > span[span %% 2 == 1] > [1] 1 3 5 7 9 11 13 15 17 19 > > ### Trickier, but perhaps instructive, is: ### > > span[TRUE & span %% 2] > [1] 1 3 5 7 9 11 13 15 17 19 > > All languages trade off various strengths and weaknesses, but I think it's fair to say that one should try to work within the paradigms that are the language's strengths when possible, R's vectorization and indexing in this example. > > Cheers, > Bert Gunter > > "The trouble with having an open mind is that people keep coming along and sticking things into it." > -- Opus (aka Berkeley Breathed in his "Bloom County" comic strip ) > > > On Sat, Jun 5, 2021 at 11:05 AM William Michels via R-help <r-help at r-project.org> wrote: >> >> > i <- 1L; span <- 1:100; result <- NA; >> > for (i in span){ >> + ifelse(i %% 2 != 0, result[i] <- TRUE, result[i] <- FALSE) >> + } >> > span[result] >> [1] 1 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31 33 35 37 39 41 43 >> 45 47 49 51 53 55 57 >> [30] 59 61 63 65 67 69 71 73 75 77 79 81 83 85 87 89 91 93 95 97 99 >> > >> >> HTH, Bill. >> >> W. Michels, Ph.D. >> >> >> On Sat, Jun 5, 2021 at 12:55 AM Stefan Evert <stefanML at collocations.de> wrote: >> > >> > > >> > > I don't understand. -- >> > > >> > > 7%%2=1 >> > > 9%%2=1 >> > > 11%%2=1 >> > > >> > > What aren't these numbers printing ? >> > > >> > > num<-0 >> > > for (i in 1:100){ >> > > num<-num+i >> > > if (num%%2 != 0) >> > > print(num) >> > > } >> > >> > Your code tests the numbers >> > >> > 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 66, ? >> > >> > and correctly prints the odd ones among them. >> > >> > But I suppose that's not what you wanted to do? >> > >> > ______________________________________________ >> > R-help at r-project.org mailing list -- To UNSUBSCRIBE and more, see >> > 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. >> >> ______________________________________________ >> R-help at r-project.org mailing list -- To UNSUBSCRIBE and more, see >> 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.
Greg Minshall
2021-Jun-09 03:28 UTC
[R] Beginner problem - using mod function to print odd numbers
> Two of R's central features as a "data science" language are that many of > its core capabilities are "vectorized" -- can calculate on whole objects > (at the user-visible interpreter level) rather than requiring explicit > loops; and that it can use object indexing in several different modalities, > here logical indexing, for extraction and replacement in whole objects such > as vectors and matrices. Not only does this typically yield simpler, more > readable code (admittedly, a subjective judgment), but it is also typically > much faster, though I grant you that this can often be overrated.i sort of wanted to circle back to this. i learned FORTRAN IV in 1968 (and the last FORTRAN program i wrote was at least 50 years ago), and i *still* write FORTRAN code, even when writing lisp, or R, or awk scripts. it's *very* hard for me to adapt to other styles. so, for that reason, i think it is very useful to help people understand and adjust to R's vector operations. maybe a way to say it might be "here is how you will get better performance, using R's vector operations..." and, then, "however, if you find it simpler, and the performance acceptable, you could do a 'for' loop like this...". (though, as this is all volunteer effort, one obviously takes what one gets.) but, i do think that helping newer users understand how to write efficient code is important. anyway, just my two cents. cheers, Greg