1

I can't figure out what is wrong with this code. I have a dataframe called Fish. I want to add a column called CombineMe that is default 0. The value would change to 501 if it meets the two criteria (either the data source = A & sample method = visual then it would equal 501 and also if the data source = B & taxon code is the three EJ, EL or RV). I can't quite figure out where I'm going wrong. I've tried adjusting where the [i] are and adding commas...

for(i in 1:length(Fish)) {
Fish$CombineMe <- 0 
if (Fish$data_source == "A" & Fish$sample_method == "visual") {
  Fish$CombineMe [i] <- 501
} else if (Fish$data_source == "B" & Fish$taxon_name == c("EJ", "EL", "RV")){
  Fish$CombineMe [i] <- 501
}}

Here's a condensed example of what Fish looks like:

Fish <- data.frame ("data_source"=c("A", "A", "B", "C", "C", "D", "D"), "sample_method"= c("visualfish", "fish", "fish", "fish", "fish", "fish", "fish"), 
                  "taxon_name"=c("EJ", "EJ", "RV", "EJ", "RV", "EL", "HR"))
Ally D
  • 165
  • 11
  • Try to use 1 of the Fish column instead of the whole dataframe itself. `length(Fish$column)`. or use `1:nrow(Fish)` – addicted Nov 16 '17 at 02:01
  • just tried that, getting the same result. I get the column CombineMe, but it has only 0 it isn't filling in any 501. This is the warning I get if (Fish$data_source == "sni" & Fish$taxon_name == ... : the condition has length > 1 and only the first element will be used – Ally D Nov 16 '17 at 02:04
  • @AllyD could you show some data? – Alejandro Andrade Nov 16 '17 at 02:05
  • `FIsh$Combine <- ifelse(Fish$data_source == "A" & Fish$sample_method == "visual", 501, ifelse(Fish$data_source == "B" & Fish$taxon_name == c("EJ", "EL", "RV"), 501, 0))` – Phil Nov 16 '17 at 02:09
  • First thing, `Fish$CombineMe <- 0 ` should be out of the loop. Second thing, compare using `i` index. For example, `Fish$data_source[i] == "A" & Fish$sample_method[i] == "visual"`. Third thing change your second `if` statement to `Fish$taxon_name[i] %in% c("EJ", "EL", "RV")` and last but not the least if you could show a [reproducible example](https://stackoverflow.com/questions/5963269/how-to-make-a-great-r-reproducible-example) there are definitely better ways to do it. – Ronak Shah Nov 16 '17 at 02:09

3 Answers3

1

Normally you need to provide how Fish dataframe looks like. I try to guess based on your given code:

Fish$CombineMe <- 0 
for(i in 1:nrow(Fish)) {

if (Fish$data_source[i] == "A" & Fish$sample_method[i] == "visual") {
  Fish$CombineMe[i] <- 501
} else if (Fish$data_source[i] == "B" & Fish$taxon_name[i] %in% c("EJ", "EL", "RV")){
  Fish$CombineMe [i] <- 501
}}

I don't think you need a loop, though. Here is the alternative method using ifelse.

Fish$CombineMe <- 0
Fish$CombineMe <- ifelse(Fish$data_source == "A" & Fish$sample_method == "visual", 501, Fish$CombineMe)
Fish$CombineMe <- ifelse(Fish$data_source == "B" & Fish$taxon_name %in% c("EJ", "EL", "RV"), 501, Fish$CombineMe)
addicted
  • 2,901
  • 3
  • 28
  • 49
1

This is the offending line of code:

Fish$CombineMe <- 0

You are zeroing out the entire column, for each iteration of the loop. Move this outside and before the loop and it should work.

But R is a vectorized language, and a much better way of making your assignment would not even use a loop at all:

cond1 <- Fish$data_source == 'A' & Fish$sample_method == 'visual'
cond2 <- Fish$data_source == "B" & Fish$taxon_name %in% c('EJ', 'EL', 'RV')
Fish$CombineMe <- ifelse(cond1 | cond2, 501, 0)
Tim Biegeleisen
  • 502,043
  • 27
  • 286
  • 360
  • thanks so much this worked great! firstly, I definitely didn't realize I was just zeroing it out. and I love the more simplified ifelse. I'm super new to R so learning something new everyday! – Ally D Nov 16 '17 at 02:20
0

The problem you are having is because everytime you loop you define Fish$CombineMe <- 0 so you are reseting the hole column to cero each time. To fix this:

Fish$CombineMe[i] <- 0 
Alejandro Andrade
  • 2,196
  • 21
  • 40