I wanted to sum individual columns by group and my first thought was to use tapply.
However, I cannot get tapply to work. Can tapply
You're looking for by. It uses the INDEX in the way that you assumed tapply would, by row.
by(df.1, df.1$state, function(x) colSums(x[,3:5]))
The problem with your use of tapply is that you were indexing the data.frame by column. (Because data.frame is really just a list of columns.) So, tapply complained that your index didn't match the length of your data.frame which is 5.