I’m looking for a way to perform multiple variable assignments based on a single conditional statement. The ifelse function performs what I want for a single variable at a time, but I’d like to be able to perform a block of statements based on a single condition.
Here is a bit of simplified example code:
within(mydata, {
if (gender == "f") {
test1 <- 1
test2 <- 2
} else {
test1 <- 0
test2 <- 0
}
test3 <- gender
test4 <- ifelse(gender == "f", 1, 0)
test5 <- ifelse(gender == "f", 2, 0)
})
Which gives the following output:
workshop gender q1 q2 q3 q4 test5 test4 test3 test2 test1
1 1 f 1 1 5 1 2 1 f 2 1
2 2 f 2 1 4 1 2 1 f 2 1
3 1 f 2 2 4 3 2 1 f 2 1
4 2 f 3 1 NA 3 2 1 f 2 1
5 1 m 4 5 2 4 0 0 m 2 1
6 2 m 5 4 5 5 0 0 m 2 1
7 1 m 5 3 4 4 0 0 m 2 1
8 2 m 4 5 5 5 0 0 m 2 1
Warning message:
In if (gender == "f") { :
the condition has length > 1 and only the first element will be used
When I run this code, test4 and test5 are correctly assigned, but test1 and test2 are incorrectly assigned, because the if statement returns the value for the first row only. Is there a way to do what I’m trying to do with test1 and test2 – run multiple statements for each row of a data frame based on a single condition?
I know I can accomplish the same result with ifelse, but I’d like to be able to group the statements together, for clarity when reading my code.
For example, I’d like to be able to group the savings calculations that I do by measure, as follows:
a.lighting.all.3 <- within(a.lighting.all.3, {
if (measure.subcategory %in% c('HID to Linear Fluorescent Retrofit',
'Hardwired CFL', 'Induction Lighting',
'Screw-In CFL', 'Specialty Screw-In CFL',
'T12 to Premium T8/T5', 'T12 to Standard T8/T5',
'T8 to Premium T8', 'T12/T8 Delamping')) {
kw.nc.v <- (base.watts - ee.watts) / 1000 * (1 + dif) * df * quantity
kwh.v <- (base.watts - ee.watts) / 1000 * (1 + eif) * op.hrs * quantity
} else if (measure.subcategory == 'Traffic Signals') {
kw.nc.v <- (base.watts - ee.watts) / 1000 * quantity
kwh.v <- (base.watts - ee.watts) / 1000 * op.hrs * quantity
} else if (measure.subcategory == 'Exit Sign Retrofit') {
} else if (measure.subcategory %in% c('LED Channel Lights',
'Cold Cathode FL')) {
} else if (measure.subcategory %in% c('Daylighting Controls',
'Occupancy Sensors')) {
} else if (measure.subcategory == 'Lighting Power Density') {
} else if (measure.subcategory == 'LED Lighting') {
}
})
Or assign sets of parameters by measure, such as:
a.lighting.all.3 <- within(a.lighting.all.3, {
switch(as.character(measure.subcategory),
"T8 to Premium T8" = {
op.hrs <- 4481
cf <- 0.93
},
"Cold Cathode FL" = {
op.hrs <- 6400
cf <- 1
},
"Exit Sign Retrofit" = {
op.hrs <- 8760
cf <- 1
},
"LED Channel Lights" = {
op.hrs <- 5110
cf <- 0.134
},
"Traffic Signals" = {
op.hrs <- ifelse(grepl("Green", measure), 3679, 4818)
df <- ifelse(grepl("Green", measure), 0.42, 0.55)
cf <- 1
},
"Daylighting Controls" = {
dsf <- esf <- 0.54 # daylight savings fraction
},
"Occupancy Sensors" = {
dsf <- 0.16 # demand savings fraction
esf <- 0.39 # energy savings fraction
},
"LED Lighting" = {
if (measure %in% c("Pedestrian NO countdown",
"Pedestrian W/ countdown")) {
cf <- 1
op.hrs <- ifelse(measure == "Pedestrian W/ countdown", 6483, 5432)
op.hrs.base <- 5432
df <- ifelse(measure == "Pedestrian W/ countdown", 0.74, 0.62)
df.base <- 0.62
} else if (measure %in% c("Refrigerated Case LED Lamps NO motion Sensors",
"Refrigerated Case LED Lamps W/ motion Sensors")) {
cf <- 1
dif <- 0.25
eif <- 0.25
op.hrs.base <- 8634
op.hrs <- ifelse(measure == "Refrigerated Case LED Lamps W/ motion Sensors",
6043, 8634)
}
}
)
})
Any ideas?
I don’t know if this answer makes you happy or not, but: if you use
plyrto operate on blocks of code you can do what you want with anifstatement.Note that this will rearrange your data into blocks by gender (in this example it doesn’t change anything), which might be undesirable …
I didn’t include the additional variables in my example, but they will get carried along correctly.