[R] Beginner problem - using mod function to print odd numbers

William Michels wjm1 @end|ng |rom c@@@co|umb|@@edu
Sun Jun 6 13:34:02 CEST 2021


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 using 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 using 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 using 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 using 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 using 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.



More information about the R-help mailing list