Using functions to change values in a data.frame

classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

Using functions to change values in a data.frame

Mark Knecht
I'm having trouble with something that looks easy. (And I'm sure it
will be easier within about 1 minute of receiving my first response.)
Thanks in advance.

I have a collection of data frames that I need to add columns, do some
calculations and then fill in the new columns. Since I have a large
number of similar data frames I want to do this with functions to make
the code more readable and ensure that every frame is done the same
way. However my simple example doesn't work as I expected it to:

Here the R example code to cut and paste. The basic idea is to copy
positive values of y into p and negative values into l.

<START COPY>

AddCols = function (MyFrame) {
        MyFrame$p<-0
        MyFrame$l<-0
        return(MyFrame)
}

BinPosNeg = function (MyFrame) {
        ifelse(MyFrame$y>0,  MyFrame$p<-MyFrame$y,  MyFrame$l<MyFrame$y)
        return(MyFrame)
}

F1 <- data.frame(x=1:10, y=-4:5)
F1
F1 <- AddCols(F1)
F1
F1 <- BinPosNeg(F1)
F1

<END COPY>

My results below are weird. After the last function call F1 acts like
BinPosNeg always evaluated MyFrame$y>0. All updates went into p - none
into l.

What am I doing wrong?

Thanks,
Mark


MY RESULTS:

> AddCols = function (MyFrame) {
+ MyFrame$p<-0
+ MyFrame$l<-0
+ return(MyFrame)
+ }
>
> BinPosNeg = function (MyFrame) {
+ ifelse(MyFrame$y>0,  MyFrame$p<-MyFrame$y,  MyFrame$l<MyFrame$y)
+ return(MyFrame)
+ }
>
> F1 <- data.frame(x=1:10, y=-4:5)
> F1
    x  y
1   1 -4
2   2 -3
3   3 -2
4   4 -1
5   5  0
6   6  1
7   7  2
8   8  3
9   9  4
10 10  5
> F1 <- AddCols(F1)
> F1
    x  y p l
1   1 -4 0 0
2   2 -3 0 0
3   3 -2 0 0
4   4 -1 0 0
5   5  0 0 0
6   6  1 0 0
7   7  2 0 0
8   8  3 0 0
9   9  4 0 0
10 10  5 0 0
> F1 <- BinPosNeg(F1)
> F1
    x  y  p l
1   1 -4 -4 0
2   2 -3 -3 0
3   3 -2 -2 0
4   4 -1 -1 0
5   5  0  0 0
6   6  1  1 0
7   7  2  2 0
8   8  3  3 0
9   9  4  4 0
10 10  5  5 0
>

______________________________________________
[hidden email] 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.
markknecht@gmail.com
Reply | Threaded
Open this post in threaded view
|

Re: Using functions to change values in a data.frame

Uwe Ligges-3


Mark Knecht wrote:

> I'm having trouble with something that looks easy. (And I'm sure it
> will be easier within about 1 minute of receiving my first response.)
> Thanks in advance.
>
> I have a collection of data frames that I need to add columns, do some
> calculations and then fill in the new columns. Since I have a large
> number of similar data frames I want to do this with functions to make
> the code more readable and ensure that every frame is done the same
> way. However my simple example doesn't work as I expected it to:
>
> Here the R example code to cut and paste. The basic idea is to copy
> positive values of y into p and negative values into l.
>
> <START COPY>
>
> AddCols = function (MyFrame) {
> MyFrame$p<-0
> MyFrame$l<-0
> return(MyFrame)
> }
>
> BinPosNeg = function (MyFrame) {
> ifelse(MyFrame$y>0,  MyFrame$p<-MyFrame$y,  MyFrame$l<MyFrame$y)


ifelse() always *evaluates* both MyFrame$p<-MyFrame$y and
MyFrame$l<MyFrame$y completely, but it just *returns* those values that
correspond to  MyFrame$y>0.

Uwe Ligges



correspond

> return(MyFrame)
> }
>
> F1 <- data.frame(x=1:10, y=-4:5)
> F1
> F1 <- AddCols(F1)
> F1
> F1 <- BinPosNeg(F1)
> F1
>
> <END COPY>
>
> My results below are weird. After the last function call F1 acts like
> BinPosNeg always evaluated MyFrame$y>0. All updates went into p - none
> into l.
>
> What am I doing wrong?
>
> Thanks,
> Mark
>
>
> MY RESULTS:
>
>> AddCols = function (MyFrame) {
> + MyFrame$p<-0
> + MyFrame$l<-0
> + return(MyFrame)
> + }
>> BinPosNeg = function (MyFrame) {
> + ifelse(MyFrame$y>0,  MyFrame$p<-MyFrame$y,  MyFrame$l<MyFrame$y)
> + return(MyFrame)
> + }
>> F1 <- data.frame(x=1:10, y=-4:5)
>> F1
>     x  y
> 1   1 -4
> 2   2 -3
> 3   3 -2
> 4   4 -1
> 5   5  0
> 6   6  1
> 7   7  2
> 8   8  3
> 9   9  4
> 10 10  5
>> F1 <- AddCols(F1)
>> F1
>     x  y p l
> 1   1 -4 0 0
> 2   2 -3 0 0
> 3   3 -2 0 0
> 4   4 -1 0 0
> 5   5  0 0 0
> 6   6  1 0 0
> 7   7  2 0 0
> 8   8  3 0 0
> 9   9  4 0 0
> 10 10  5 0 0
>> F1 <- BinPosNeg(F1)
>> F1
>     x  y  p l
> 1   1 -4 -4 0
> 2   2 -3 -3 0
> 3   3 -2 -2 0
> 4   4 -1 -1 0
> 5   5  0  0 0
> 6   6  1  1 0
> 7   7  2  2 0
> 8   8  3  3 0
> 9   9  4  4 0
> 10 10  5  5 0
>
> ______________________________________________
> [hidden email] 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.

______________________________________________
[hidden email] 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.
Reply | Threaded
Open this post in threaded view
|

Re: Using functions to change values in a data.frame

Duncan Murdoch
In reply to this post by Mark Knecht
On 30/06/2009 6:47 PM, Mark Knecht wrote:

> I'm having trouble with something that looks easy. (And I'm sure it
> will be easier within about 1 minute of receiving my first response.)
> Thanks in advance.
>
> I have a collection of data frames that I need to add columns, do some
> calculations and then fill in the new columns. Since I have a large
> number of similar data frames I want to do this with functions to make
> the code more readable and ensure that every frame is done the same
> way. However my simple example doesn't work as I expected it to:
>
> Here the R example code to cut and paste. The basic idea is to copy
> positive values of y into p and negative values into l.
>
> <START COPY>
>
> AddCols = function (MyFrame) {
> MyFrame$p<-0
> MyFrame$l<-0
> return(MyFrame)
> }
>
> BinPosNeg = function (MyFrame) {
> ifelse(MyFrame$y>0,  MyFrame$p<-MyFrame$y,  MyFrame$l<MyFrame$y)
> return(MyFrame)
> }
>
> F1 <- data.frame(x=1:10, y=-4:5)
> F1
> F1 <- AddCols(F1)
> F1
> F1 <- BinPosNeg(F1)
> F1
>
> <END COPY>
>
> My results below are weird. After the last function call F1 acts like
> BinPosNeg always evaluated MyFrame$y>0. All updates went into p - none
> into l.
>
> What am I doing wrong?

Misunderstanding ifelse().  It evaluates both value args, and returns
the elements from one of them, depending on the corresponding element of
the condition.  So you don't want it.  I think you want

   pos <- MyFrame$y > 0
   MyFrame$p[pos] <- MyFrame$y[pos]
   MyFrame$l[!pos] <- MyFrame$y[!pos]

Duncan Murdoch

>
> Thanks,
> Mark
>
>
> MY RESULTS:
>
>> AddCols = function (MyFrame) {
> + MyFrame$p<-0
> + MyFrame$l<-0
> + return(MyFrame)
> + }
>> BinPosNeg = function (MyFrame) {
> + ifelse(MyFrame$y>0,  MyFrame$p<-MyFrame$y,  MyFrame$l<MyFrame$y)
> + return(MyFrame)
> + }
>> F1 <- data.frame(x=1:10, y=-4:5)
>> F1
>     x  y
> 1   1 -4
> 2   2 -3
> 3   3 -2
> 4   4 -1
> 5   5  0
> 6   6  1
> 7   7  2
> 8   8  3
> 9   9  4
> 10 10  5
>> F1 <- AddCols(F1)
>> F1
>     x  y p l
> 1   1 -4 0 0
> 2   2 -3 0 0
> 3   3 -2 0 0
> 4   4 -1 0 0
> 5   5  0 0 0
> 6   6  1 0 0
> 7   7  2 0 0
> 8   8  3 0 0
> 9   9  4 0 0
> 10 10  5 0 0
>> F1 <- BinPosNeg(F1)
>> F1
>     x  y  p l
> 1   1 -4 -4 0
> 2   2 -3 -3 0
> 3   3 -2 -2 0
> 4   4 -1 -1 0
> 5   5  0  0 0
> 6   6  1  1 0
> 7   7  2  2 0
> 8   8  3  3 0
> 9   9  4  4 0
> 10 10  5  5 0
>
> ______________________________________________
> [hidden email] 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.

______________________________________________
[hidden email] 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.
Reply | Threaded
Open this post in threaded view
|

Re: Using functions to change values in a data.frame

Mark Knecht
On Tue, Jun 30, 2009 at 3:57 PM, Duncan Murdoch<[hidden email]> wrote:

> On 30/06/2009 6:47 PM, Mark Knecht wrote:
>>
>> I'm having trouble with something that looks easy. (And I'm sure it
>> will be easier within about 1 minute of receiving my first response.)
>> Thanks in advance.
>>
>> I have a collection of data frames that I need to add columns, do some
>> calculations and then fill in the new columns. Since I have a large
>> number of similar data frames I want to do this with functions to make
>> the code more readable and ensure that every frame is done the same
>> way. However my simple example doesn't work as I expected it to:
>>
>> Here the R example code to cut and paste. The basic idea is to copy
>> positive values of y into p and negative values into l.
>>
>> <START COPY>
>>
>> AddCols = function (MyFrame) {
>>        MyFrame$p<-0
>>        MyFrame$l<-0
>>        return(MyFrame)
>> }
>>
>> BinPosNeg = function (MyFrame) {
>>        ifelse(MyFrame$y>0,  MyFrame$p<-MyFrame$y,  MyFrame$l<MyFrame$y)
>>        return(MyFrame)
>> }
>>
>> F1 <- data.frame(x=1:10, y=-4:5)
>> F1
>> F1 <- AddCols(F1)
>> F1
>> F1 <- BinPosNeg(F1)
>> F1
>>
>> <END COPY>
>>
>> My results below are weird. After the last function call F1 acts like
>> BinPosNeg always evaluated MyFrame$y>0. All updates went into p - none
>> into l.
>>
>> What am I doing wrong?
>
> Misunderstanding ifelse().  It evaluates both value args, and returns the
> elements from one of them, depending on the corresponding element of the
> condition.  So you don't want it.  I think you want
>
>  pos <- MyFrame$y > 0
>  MyFrame$p[pos] <- MyFrame$y[pos]
>  MyFrame$l[!pos] <- MyFrame$y[!pos]
>
> Duncan Murdoch
>

OK, clearly I have some learning to do here. Only my 3rd day with R.

Your response and Phil's are the same and they both work which is
great. The following evaluates correctly TRUE or FALSE looking at the
data.frame. Good so far.

pos <- MyFrame$y > 0

But how does the following actually work? What's it doing?

MyFrame$p[pos] <- MyFrame$y[pos]

Anyway, I have a solution which is great. Thanks. And now I'll try to
get comfortable with how these last two equations actually work.

Cheers,
Mark.


>>
>> Thanks,
>> Mark
>>
>>
>> MY RESULTS:
>>
>>> AddCols = function (MyFrame) {
>>
>> + MyFrame$p<-0
>> + MyFrame$l<-0
>> + return(MyFrame)
>> + }
>>>
>>> BinPosNeg = function (MyFrame) {
>>
>> + ifelse(MyFrame$y>0,  MyFrame$p<-MyFrame$y,  MyFrame$l<MyFrame$y)
>> + return(MyFrame)
>> + }
>>>
>>> F1 <- data.frame(x=1:10, y=-4:5)
>>> F1
>>
>>    x  y
>> 1   1 -4
>> 2   2 -3
>> 3   3 -2
>> 4   4 -1
>> 5   5  0
>> 6   6  1
>> 7   7  2
>> 8   8  3
>> 9   9  4
>> 10 10  5
>>>
>>> F1 <- AddCols(F1)
>>> F1
>>
>>    x  y p l
>> 1   1 -4 0 0
>> 2   2 -3 0 0
>> 3   3 -2 0 0
>> 4   4 -1 0 0
>> 5   5  0 0 0
>> 6   6  1 0 0
>> 7   7  2 0 0
>> 8   8  3 0 0
>> 9   9  4 0 0
>> 10 10  5 0 0
>>>
>>> F1 <- BinPosNeg(F1)
>>> F1
>>
>>    x  y  p l
>> 1   1 -4 -4 0
>> 2   2 -3 -3 0
>> 3   3 -2 -2 0
>> 4   4 -1 -1 0
>> 5   5  0  0 0
>> 6   6  1  1 0
>> 7   7  2  2 0
>> 8   8  3  3 0
>> 9   9  4  4 0
>> 10 10  5  5 0
>>
>> ______________________________________________
>> [hidden email] 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.
>
>

______________________________________________
[hidden email] 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.
markknecht@gmail.com
Reply | Threaded
Open this post in threaded view
|

Re: Using functions to change values in a data.frame

Duncan Murdoch
On 30/06/2009 7:13 PM, Mark Knecht wrote:

> On Tue, Jun 30, 2009 at 3:57 PM, Duncan Murdoch<[hidden email]> wrote:
>> On 30/06/2009 6:47 PM, Mark Knecht wrote:
>>> I'm having trouble with something that looks easy. (And I'm sure it
>>> will be easier within about 1 minute of receiving my first response.)
>>> Thanks in advance.
>>>
>>> I have a collection of data frames that I need to add columns, do some
>>> calculations and then fill in the new columns. Since I have a large
>>> number of similar data frames I want to do this with functions to make
>>> the code more readable and ensure that every frame is done the same
>>> way. However my simple example doesn't work as I expected it to:
>>>
>>> Here the R example code to cut and paste. The basic idea is to copy
>>> positive values of y into p and negative values into l.
>>>
>>> <START COPY>
>>>
>>> AddCols = function (MyFrame) {
>>>        MyFrame$p<-0
>>>        MyFrame$l<-0
>>>        return(MyFrame)
>>> }
>>>
>>> BinPosNeg = function (MyFrame) {
>>>        ifelse(MyFrame$y>0,  MyFrame$p<-MyFrame$y,  MyFrame$l<MyFrame$y)
>>>        return(MyFrame)
>>> }
>>>
>>> F1 <- data.frame(x=1:10, y=-4:5)
>>> F1
>>> F1 <- AddCols(F1)
>>> F1
>>> F1 <- BinPosNeg(F1)
>>> F1
>>>
>>> <END COPY>
>>>
>>> My results below are weird. After the last function call F1 acts like
>>> BinPosNeg always evaluated MyFrame$y>0. All updates went into p - none
>>> into l.
>>>
>>> What am I doing wrong?
>> Misunderstanding ifelse().  It evaluates both value args, and returns the
>> elements from one of them, depending on the corresponding element of the
>> condition.  So you don't want it.  I think you want
>>
>>  pos <- MyFrame$y > 0
>>  MyFrame$p[pos] <- MyFrame$y[pos]
>>  MyFrame$l[!pos] <- MyFrame$y[!pos]
>>
>> Duncan Murdoch
>>
>
> OK, clearly I have some learning to do here. Only my 3rd day with R.
>
> Your response and Phil's are the same and they both work which is
> great. The following evaluates correctly TRUE or FALSE looking at the
> data.frame. Good so far.
>
> pos <- MyFrame$y > 0
>
> But how does the following actually work? What's it doing?
>
> MyFrame$p[pos] <- MyFrame$y[pos]

It uses the logical vector pos to index two other vectors.  On the right
hand side, that selects all the entries of y where pos is TRUE.  On the
left hand side, that says to replace all the entries of p where pos is
TRUE.  Since y and p are the same length (both being columns of a data
frame), that's the same thing as replacing p by y in those cases where
pos is TRUE.

Duncan Murdoch

>
> Anyway, I have a solution which is great. Thanks. And now I'll try to
> get comfortable with how these last two equations actually work.
>
> Cheers,
> Mark.
>
>
>>> Thanks,
>>> Mark
>>>
>>>
>>> MY RESULTS:
>>>
>>>> AddCols = function (MyFrame) {
>>> + MyFrame$p<-0
>>> + MyFrame$l<-0
>>> + return(MyFrame)
>>> + }
>>>> BinPosNeg = function (MyFrame) {
>>> + ifelse(MyFrame$y>0,  MyFrame$p<-MyFrame$y,  MyFrame$l<MyFrame$y)
>>> + return(MyFrame)
>>> + }
>>>> F1 <- data.frame(x=1:10, y=-4:5)
>>>> F1
>>>    x  y
>>> 1   1 -4
>>> 2   2 -3
>>> 3   3 -2
>>> 4   4 -1
>>> 5   5  0
>>> 6   6  1
>>> 7   7  2
>>> 8   8  3
>>> 9   9  4
>>> 10 10  5
>>>> F1 <- AddCols(F1)
>>>> F1
>>>    x  y p l
>>> 1   1 -4 0 0
>>> 2   2 -3 0 0
>>> 3   3 -2 0 0
>>> 4   4 -1 0 0
>>> 5   5  0 0 0
>>> 6   6  1 0 0
>>> 7   7  2 0 0
>>> 8   8  3 0 0
>>> 9   9  4 0 0
>>> 10 10  5 0 0
>>>> F1 <- BinPosNeg(F1)
>>>> F1
>>>    x  y  p l
>>> 1   1 -4 -4 0
>>> 2   2 -3 -3 0
>>> 3   3 -2 -2 0
>>> 4   4 -1 -1 0
>>> 5   5  0  0 0
>>> 6   6  1  1 0
>>> 7   7  2  2 0
>>> 8   8  3  3 0
>>> 9   9  4  4 0
>>> 10 10  5  5 0
>>>
>>> ______________________________________________
>>> [hidden email] 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.
>>

______________________________________________
[hidden email] 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.