Reputation: 49
I have a table with dates in column 1 (Column titled "Date") and values in columns 2 through 5 (Columns titled "A"->"D").
Date A B C D
1/1/16 12 75 38 88
1/2/16 32 76 44 34
etc.
I need to create additional 6th column E that contains the following:
For each row:
If value in column A > B > C then value in column E = X
If value in column A < B < C then value in column E = Y
for anything else value in column E = Z
What is the best way to do this?
Upvotes: 0
Views: 1146
Reputation: 1076
I think this should work fine:
set.seed(1)
myframe = data.frame(date=1:10, a=sample(1:10), b=sample(1:10), c=sample(1:10), d=sample(1:10), e=NA)
myframe[myframe$a > myframe$b & myframe$b > myframe$c, "e"] = "x"
myframe[myframe$a < myframe$b & myframe$b < myframe$c, "e"] = "y"
myframe[is.na(myframe$e), "e"] = "z"
myframe
Gives
date a b c d e 1 1 3 3 10 5 z 2 2 4 2 2 6 z 3 3 5 6 6 4 z 4 4 7 10 1 2 z 5 5 2 5 9 10 y 6 6 8 7 8 8 z 7 7 9 8 7 9 x 8 8 6 4 5 1 z 9 9 10 1 3 7 z 10 10 1 9 4 3 z
if x <- 1:4
gives 1 2 3 4
then x < - 1:4 < 3
is TRUE TRUE FALSE FALSE
. So, someFrame[x, "someCol"]
selects that col from rows where x is TRUE, i.e. the first and second rows. The same works for vectors, so c("a", "b", "c", "d")[x]
returns a b
. I've heard this called "logical indexing", for what it's worth.
Upvotes: 1
Reputation: 23216
# Here I'm simulating your original dataset
df <- data.frame(Date=seq(Sys.Date(),Sys.Date()+9,by=1), A = seq(1,20,2),
B = rep(10,1,1), C=abs(rnorm(10)), D = rnorm(10))
# Create E
df$E <- NA
df$E[df$A > df$B & df$B > df$C] <- "X"
df$E[df$A < df$B & df$B < df$C] <- "Y"
df$E[is.na(df$E)] <- "Z"
df
Date A B C D E
1 2016-06-29 1 10 0.5833273005 -0.25244803522 Z
2 2016-06-30 3 10 0.4291374487 0.01669504752 Z
3 2016-07-01 5 10 1.7079045597 1.28413741595 Z
4 2016-07-02 7 10 0.2286708311 1.16421926818 Z
5 2016-07-03 9 10 0.6216853471 1.08934300378 Z
6 2016-07-04 11 10 1.4662821456 -0.58322427720 X
7 2016-07-05 13 10 0.8255102263 0.65217873906 X
8 2016-07-06 15 10 1.6185672627 0.04195996408 X
9 2016-07-07 17 10 0.6752993011 -2.31746231694 X
10 2016-07-08 19 10 0.2901133125 0.97969860678 X
# Create E only for a subset of rows, like 6:10
df$E <- NA
df$E[1:5] <- "nothing applied to this row"
df$E[df$A > df$B & df$B > df$C & 6:10] <- "X"
df$E[df$A < df$B & df$B < df$C & 6:10] <- "Y"
df$E[is.na(df$E) & 6:10] <- "Z"
df
Date A B C D E
1 2016-06-29 1 10 0.5833273005 -0.25244803522 nothing applied to this row
2 2016-06-30 3 10 0.4291374487 0.01669504752 nothing applied to this row
3 2016-07-01 5 10 1.7079045597 1.28413741595 nothing applied to this row
4 2016-07-02 7 10 0.2286708311 1.16421926818 nothing applied to this row
5 2016-07-03 9 10 0.6216853471 1.08934300378 nothing applied to this row
6 2016-07-04 11 10 1.4662821456 -0.58322427720 X
7 2016-07-05 13 10 0.8255102263 0.65217873906 X
8 2016-07-06 15 10 1.6185672627 0.04195996408 X
9 2016-07-07 17 10 0.6752993011 -2.31746231694 X
10 2016-07-08 19 10 0.2901133125 0.97969860678 X
Upvotes: 1