tom tom - 3 months ago 18
R Question

Conditional Counter In New Column - R

I'd like help creating a function or loop that adds a value to a new column based on values in the same row of other columns. The goal is to create a kind of scoring system for a survey dataset.

Here's a sample dataframe

dfp <- data.frame(id=c("resp1", "resp2", "resp3"),
cat1=c("gov", "biz", "biz"),
cat2=c("dem", "gop", "dem"),
liberal=c(0,0,0),
conservative=c(0,0,0))


In the above set, I imagine "gov" and "dem" both at 1 point to the liberal column, while "biz" and "gop" add a point each to the conservative column. So, the ideal dataframe would be:

dfp <- data.frame(id=c("resp1", "resp2", "resp3"),
cat1=c("gov", "biz", "biz"),
cat2=c("dem", "gop", "dem"),
liberal=c(2,0,1),
conservative=c(0,2,1))


I tried a for loop, but it didn't work.

for (i in length(dfp$liberal)){
if (dfp[i,][,2] == "gov"){
dfp[i,]$liberal = dfp[i,]$liberal + 1
}
if (dfp[i,][,3]=="gop"){
dfp[i,]$conservative = dfp[i,]$conservative + 1
}
}


If i get rid of the "i" iterator, the loop correctly adds the number liberal and conservative, but it adds it uniformly to all the rows.

thanks for any help and let me know if i can make this question any clearer. I'm a little new to loops, do if you also happen to have a function that would help me diagnose what i'm doing wrong, feel free to add to your explanation. thanks so much.

Answer

Just so you can see what some of your indexing problems were, here's a working sample of code based on your for loop.

dfp <- data.frame(id=c("resp1", "resp2", "resp3"), 
                  cat1=c("gov", "biz", "biz"), 
                  cat2=c("dem", "gop", "dem"),
                  liberal=c(0,0,0), 
                  conservative=c(0,0,0))

          #* Use seq_along and not length (or use 1:length())
for (i in seq_along(dfp$liberal)){
  if (dfp$cat1[i] == "gov"){
    dfp$liberal[i] = dfp$liberal[i] + 1
  }
  if (dfp$cat2[i]=="gop"){
    dfp$conservative[i] = dfp$conservative[i] + 1
  }
}

dfp

But the other answers will be more efficient.