[R] using nested ifelse and rowSums to create new variable?

Marc Schwartz
2006-11-21T21:24:41Z

On Tue, 2006-11-21 at 14:26 -0600, Tony N. Brown wrote:
> Dear R-help community,
>
> If I have a data.frame df as follows:
>
> > df
>    x1 x2 x3 x4 x5 x6
> 1   5  5  1  1  2  1
> 2   5  5  5  5  1  5
> 3   1  5  5  5  5  5
> 4   5  5  1  4  5  5
> 5   5  1  5  2  4  1
> 6   5  1  5  4  5  1
> 7   5  1  5  4  4  5
> 8   5  1  1  1  1  5
> 9   1  5  1  1  2  5
> 10  5  1  5  4  5  5
> 11  1  5  5  2  1  1
> 12  5  5  5  4  4  1
> 13  1  5  1  4  4  1
> 14  1  1  5  4  5  5
> 15  1  5  5  4  5  1
> 16  1  1  5  5  5  1
> 17  5  5  5  2  2  5
> 18  1  5  1  5  5  5
> 19  5  5  5  2  4  5
> 20  1  1  5  2  4  5
>
> How can I create a variable that captures the pattern of responses
> and counts across rows?
>
> I used the ifelse function and that works fine for the first two
> conditions (see R code below). But I need help figuring out how to
> count the number of scores in each row for columns x3, x4, x5, and
> x6 that are less than 4, conditional upon an ifelse. I then want to
> assign a value to the new variable based upon the count.
>
> The new variable I want to create is called dep. Here's my R code:
>
> dep<-with(df,
>   ifelse((x1==5) & (x2==5), 0,
>   ifelse((x1==1 & x2==1), 1,
>
>   ifelse((x1==1 & x2==5) | (x1==5 & x2==1) &
>   (rowSums(df[ ,c(x3, x4, x5, x6)]<4) ==1), 2,
>   ifelse((x1==1 & x2==5) | (x1==5 & x2==1) &
>   (rowSums(df[ ,c(x3, x4, x5, x6)]<4) ==2), 3,
>   ifelse((x1==1 & x2==5) | (x1==5 & x2==1) &
>   (rowSums(df[ ,c(x3, x4, x5, x6)]<4) ==3), 4,
>
> 99))))))
>
> dep
>  0  1  2 99
>  6  3  6  5
>
> I expected dep to range from 0 to 4 and its length to be equal to
> 20.
>
> Thanks in advance for your help and suggestions.

I may be a bit off in what your desired end result is, but perhaps this
will provide some insight. I renamed your data frame to DF, since df is
a function:

> apply(DF[, -(1:2)], 1, function(x) sum(x < 4))
 1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20
 4  1  0  1  2  1  0  3  3  0  3  1  2  0  1  1  2  1  1  1

# Row sums are going to be 2 (1 + 1), 6 (5 + 1 or 1 + 5),
# or 10 (5 + 5)
> rowSums(DF[, 1:2])
 1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20
10 10  6 10  6  6  6  6  6  6  6 10  6  2  6  2 10  6 10  2


# Create a cross tabulation of the above results and format
# Here I coerce the rowSums to a factor and set the factor labels
# to be used as the column names in the table
TAB <- table(apply(DF[, -(1:2)], 1, function(x) sum(x < 4)),
             factor(rowSums(DF[, 1:2]),
                    labels = c("(1,1)", "(5,1)|(1,5)",
"(5,5)")))

# Add row and column totals
TAB <- addmargins(TAB)


> TAB

      (1,1) (5,1)|(1,5) (5,5) Sum
  0       1           3     0   4
  1       2           3     4   9
  2       0           2     1   3
  3       0           3     0   3
  4       0           0     1   1
  Sum     3          11     6  20


HTH,

Marc Schwartz