Showing posts with label R data manipulation. Show all posts
Showing posts with label R data manipulation. Show all posts

Saturday, August 13, 2011

R - extract year, month etc.... from date

extract year, month, day… from date

  • create vector of dates in standard format
my.dates <- as.Date(format(ISOdatetime(2000:2009,1:10,1:5,0,0,0),"%Y-%m-%d"))
my.dates
 [1] "2000-01-01" "2001-02-02" "2002-03-03" "2003-04-04" "2004-05-05"
 [6] "2005-06-01" "2006-07-02" "2007-08-03" "2008-09-04" "2009-10-05"
(make sure your object is of date fromat, check it with str(your.object)
  • extract years using format:
my.years <- format(my.dates,"%Y") # %y without century
my.years
 [1] "2000" "2001" "2002" "2003" "2004" "2005" "2006" "2007" "2008" "2009"
  • or months
my.months <- format(my.dates,"%m")
my.months
 [1] "01" "02" "03" "04" "05" "06" "07" "08" "09" "10"
  • or names of month (in current local)
my.months <- format(my.dates,"%b") # %B for long form
my.months
 [1] "Jan" "Feb" "Mär" "Apr" "Mai" "Jun" "Jul" "Aug" "Sep" "Okt"
  • or days (of month)
my.days <- format(my.dates,"%d")
my.days
 [1] "01" "02" "03" "04" "05" "01" "02" "03" "04" "05"
  • or week day (in current local)
my.days <- format(my.dates,"%a") # %A for long form, %w (0-6) of %u (1-7) for number
my.days
 [1] "Sa" "Fr" "So" "Fr" "Mi" "Mi" "So" "Fr" "Do" "Mo"
  • or day of year
my.days <- format(my.dates,"%j")
my.days
 [1] "001" "033" "062" "094" "126" "152" "183" "215" "248" "278"
  • or week of year (sunday as first day of the week)
my.weeks <- format(my.dates,"%U") # %W for monday = first day of the week
my.weeks
 [1] "00" "04" "09" "13" "18" "22" "27" "30" "35" "40"
  • local format of date
my.days <- format(my.dates,"%x")
my.days
 [1] "01.01.2000" "02.02.2001" "03.03.2002" "04.04.2003" "05.05.2004"
 [6] "01.06.2005" "02.07.2006" "03.08.2007" "04.09.2008" "05.10.2009"

R - subscripting 3

subsetting with logical indices

  • elements corresponding to a TRUE in the subscript vector are selected, those corresponding to a FALSE are excluded, NAs in the the logical subscript vector produce NAs
my.vector <- letters[1:10] # vector of a...j
my.vector
 [1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j"
my.index <- rep(c(TRUE,FALSE),5) # the subscript vector (of length 10)
my.index
 [1]  TRUE FALSE  TRUE FALSE  TRUE FALSE  TRUE FALSE  TRUE FALSE
my.vector[my.index]
[1] "a" "c" "e" "g" "i"
  • if the subscript vector consists of less elements than the subscripted vector, it is repeated as many times as necessary (warning if the the vector length is not a multiple of the length of the subscript vector)
short.index <- c(T,F) # T is the same as TRUE, F as FALSE
short.index
[1]  TRUE FALSE
my.vector[short.index] # has the same result as above
[1] "a" "c" "e" "g" "i"
  • if the subscript vector is longer than the vector for every TRUE or NA entry without target a NA is produced
short.vector <- letters[1:3]
short.vector
[1] "a" "b" "c"
my.index <- rep(c(T,F,NA),2)
my.index
[1]  TRUE FALSE    NA  TRUE FALSE    NA
short.vector[my.index]
[1] "a" NA  NA  NA

R - subscripting 2

subsetting with character indices - vectors and lists

  • extract elements of named vectors, lists
named.x <- 1:10  # produce a vector containing the numbers 1...10
named.x   #  has no names yet
 [1]  1  2  3  4  5  6  7  8  9 10
  • if the object has no names, NAs are produced
named.x["one"]
[1] NA
  • name the vector:
names(named.x) <- c("one","two","three","four","five","six","seven","eight","nine","ten")
named.x
  one   two three  four  five   six seven eight  nine   ten 
    1     2     3     4     5     6     7     8     9    10
  • now it works
named.x["one"]
one 
  1
  • if names are duplicated only the first match is returned (the value with the lowest index)
names(named.x)<-rep(c("one","two","three","four","five"),rep(2,5))
named.x
  one   one   two   two three three  four  four  five  five 
    1     2     3     4     5     6     7     8     9    10
named.x[c("one","two","three")]
  one   two three 
    1     3     5
  • NA is returned if a name do not match any element
named.x["twenty"]
<NA> 
  NA
  • NA is returned if a subscript is character NA
named.x[c("one",NA,"three")]
  one  <NA> three 
    1    NA     5
  • to find all occurences one can use %in% and then subset with the logical vector (you can do this in one step)
named.x[names(named.x) %in% c("one","two")]
one one two two 
  1   2   3   4

Monday, August 1, 2011

R - subscripting

subsetting

  • creating a list for examples
myl <- list(one=10,two=20,three=30)
myi <- "one"
one
  • subsetting is carried out with three different operators:
    • dollar: $
    • square bracket: [
    • double square bracket: [[
  • these are generic functions
  • there are four basic types of subscript indices
    • positive integers
    • negative integers
    • logical vectors
    • character vectors
  • the first (left-most) index moves the fastest, the right-most index is the slowest (so a matrix is filled column by column)

the square bracket

  • the returned value is of the same type of the value it is applied to
myl[c(1,2)]
10 20
  • evaluate its second argument
myl[myi]
10
  • does not use partial matching when extracting named elements
myl["on"]
  • cannot be used for subscripting environments

the double square bracket

  • extract a single value
myl[[1]]
10
  • evaluate its second argument
myl[[myi]]
10
  • does not use partial matching when extracting named elements
myl[["on"]]

the dollar

  • extract a single value
myl$two
20
  • does not evaluate its second argument
myl$myi
  • uses partial matching extracting named elements
myl$on
10
  • cannot be used for subscripting atomic vectors

subsetting with positive indices

  • vector of positive integer values to indicate the set to be extracted
myv <- 1:10 
myi <- c(2,4,7)
myv[myi]
myv[c(2,4,7)]
[1] 2 4 7
[1] 2 4 7
  • if the subscript is larger than the length of the vector, NAs are produce
myv[c(1,11,3)]
[1]  1 NA  3
  • NA as subscript produces also a NA
myv[c(1,11,NA)]
[1]  1 NA NA
  • zero as subscript will be ignored
myv[c(1,2,0,3)]
[1] 1 2 3
  • if the subscript vector has the length zero, the result is also of length zero
myi <- numeric()
myv[myi]
integer(0)
  • example: select elements which have even numbered subscripts
v <- rnorm(20)
myi <- seq(2,length(v),by=2)
myi
v[myi]
 [1]  2  4  6  8 10 12 14 16 18 20
 [1]  0.35380115 -0.02156840 -1.51804278  0.38278037  0.03867578 -1.25803279
 [7]  0.62863255  0.07111270 -0.73416837  0.18966622

subsetting with negative indices

  • subscript vector consists of negative integer values indicating the indices not to be extracted
  • zero as subscript will be ignored
myv[-c(1,2,0,3)]
[1]  4  5  6  7  8  9 10
  • NAs are not allowed
myv[-c(1,NA,3)]
Error in myv[-c(1, NA, 3)] : 
  nur Nullen dürfen mit negativen Indizes gemischt werden
  • zero length subscript produces zero length result
myv <- 1:10 
myi <- numeric()
myv[-myi]
 integer(0)
  • positive and negatives subscripts cannot be mixed

to be continued... (most parts taken from Gentleman, R Programming for Bioinformatics) …

Tuesday, July 26, 2011

R - recode() data

recode() - from package lordif

library(lordif)  # maybe you have first to install the package (install.packages("lordif"))
  • creating example data
z <- sample(0:1, 25, replace=T)
original <- c(0,1)
new <- c("boy", "girl")
z
original
new
z:  1 1 1 0 0 0 1 1 1 1 0 0 1 1 1 1 0 1 1 1 1 1 1 1 0
original: 0 1
new:  "boy"  "girl"
  • so z is a vector consisting of 1 and 0
  • original contains the distinct values of z
  • and new contains the values which should replace the original values in the following way: the first item of original is replaced by the first value of new, the second by the second etc pp
z <- recode(z, original, new)
z
 [1] "girl" "girl" "girl" "boy"  "boy"  "boy"  "girl" "girl" "girl" "girl"
[11] "boy"  "boy"  "girl" "girl" "girl" "girl" "boy"  "girl" "girl" "girl"
[21] "girl" "girl" "girl" "girl" "boy"

u

Wednesday, July 20, 2011

R - t.test for subsets of a data frame (ddply or tapply)

(two sample t-test for groups in data frame here)
First we create a data frame, on which we can work
x <- rnorm(100)                 
y <- sample(1:3, 100, replace=T)
z <- sample(1:2, 100, replace=T)

df <- data.frame(group=y,sex=z,sds=x)
head(df)
group sex       sds
1     1   2 1.3412663
2     1   1 0.8000326
3     2   2 0.0371029
4     1   2 0.2064684
5     1   2 1.6429816
6     3   1 1.3271138
In the following I use ddply() from the plyr-package, so if you did not install and/or load it you have to do it now - the command library() without any argument gives you a list of the installed packages:
install.packages("plyr") # install the package
library(plyr) # load it
Here is the function for doing the t.tests:
t.test.plyr <- function(x, var, mean=0 ){
  y <- rep(NA,10)
  y[6] <- nrow(x)[1]              # count observations
  if(nrow(x) < 2) return(y)       # exits if too less observations
  res <- t.test(x[var], mu=mean)  # doing the test

  y[1] <- res$statistic           # extract values of interest
  y[2] <- res$p.value      
  y[3] <- res$estimate     
  y[4] <- res$conf.int[1]  
  y[5] <- res$conf.int[2]  
  y[7] <- res$parameter    
  y[8] <- res$method       
  y[9] <- res$alternative  
  y[10] <- res$null.value   

  names(y) <- c("statistic","p.value","estimate","conf.int1", "conf.int2", "nobs","dof","method","alternative","null.value")
  y 
}

where t.test.plyr() is a function of:
- x - the data frame
- var - the variable which should be testet
- mean - the mean of the t-test

now we can use ddply in the following way:
result <- ddply(df, .(group, sex), t.test.plyr, "sds")
result
group sex           statistic           p.value            estimate
1     1   1   0.774917157596946 0.445379429071851   0.132214420988956
2     1   2  -0.415594591752269  0.68359099812399 -0.0987341821354776
3     2   1   0.130257003222609 0.899578855830346  0.0602600950757679
4     2   2 -0.0579045286518569 0.954965406753824 -0.0150105343694587
5     3   1    1.18044920537142 0.256202807853187   0.406567809727671
6     3   2    1.49215606704641  0.15126489039304   0.294865619363907
           conf.int1         conf.int2 nobs dof            method alternative
1 -0.218494854049804 0.482923696027717   27  26 One Sample t-test   two.sided
2 -0.605109702463049 0.407641338192093   16  15 One Sample t-test   two.sided
3  -1.00655416438508  1.12707435453662    9   8 One Sample t-test   two.sided
4 -0.592608791299465 0.562587722560548   11  10 One Sample t-test   two.sided
5 -0.327541518602652  1.14067713805799   16  15 One Sample t-test   two.sided
6 -0.117342538637965  0.70707377736578   21  20 One Sample t-test   two.sided
  null.value
1          0
2          0
3          0
4          0
5          0
6          0
If you want to change the mu in you t.test, add the argument mean:
result <- ddply(df, .(group, sex), t.test.plyr, "sds", mean=1)
result
If there is no need or you do not want a data frame as result you can just use tapply(). tapply results in a list with as many elements as subsets, each element contains the results of each t.test (as list).
res <- tapply(df$sds, list(df$sex,df$group), t.test)
res
1      2      3     
1 List,9 List,9 List,9
2 List,9 List,9 List,9
So the first element of res contains the t.test results for sex=1 and group=1 etc pp
res[[1]]
One Sample t-test

data:  X[[1L]] 
t = 0.7749, df = 26, p-value = 0.4454
alternative hypothesis: true mean is not equal to 0 
95 percent confidence interval:
 -0.2184949  0.4829237 
sample estimates:
mean of x 
0.1322144

Thursday, July 7, 2011

R - generate a vector with names of months (like LETTERS)

> format(ISOdatetime(2000,1:12,1,0,0,0),"%b")
gives:
 [1] "Jan" "Feb" "Mrz" "Apr" "Mai" "Jun" "Jul" "Aug" "Sep" "Okt" "Nov" "Dez"
where the month names depend on local settings. If you use %B instead of %b you get the non abbreviated months. How ever, there is also an easier way if you want the months in English: the vector
> month.name
 
gives
 [1] "January"   "February"  "March"     "April"     "May"       "June"     
 [7] "July"      "August"    "September" "October"   "November"  "December" 
or
> month.abb
 
gives
 [1] "Jan" "Feb" "Mar" "Apr" "May" "Jun" "Jul" "Aug" "Sep" "Oct" "Nov" "Dec"

Wednesday, July 6, 2011

R - ddply

ddply

dataframe in dataframe out

example

  • first we create a data frame with the following columns: id, date, value
  • to create the id column we use rep(), where the first argument 1:5 (the vector (1,2,3,4,5)) is repeated five times, so we have a vector with length 25
  • the vector dates is generated in the following way:
    • generate a vector of random numbers between 1 and 1500 and length 25 (sample.int())
    • use as.Date with the origin argument, this converts the integers into Date, where the the origin is day 0 (in the case 0 is convert to the origin i.e. 2000-01-01, 1 is mapped to 2000-01-02 etc pp, so we get a vector of dates between 2000 and beginning 2005
  • vals are generated by the random numbers function rnorm() (normal distributed with mean 5 and standard deviation 1
  • last but not least put the three together in one data frame (and let us show the first lines)
id <- rep(1:5,5)
dates <- as.Date(sample.int(1500, 25, replace=T), origin="2000-01-01") 
vals <- rnorm(25, mean=5, sd=1)
df <- data.frame(id=id, date=dates, val=vals)
head(df)
  id       date      val
1  1 2001-12-31 5.778680
2  2 2002-08-02 6.982799
3  3 2002-04-23 5.925903
4  4 2000-08-03 3.527375
5  5 2002-08-29 5.239211
6  1 2003-01-28 5.118337
  • id encodes a person, date contains the day of the measurement and val the values
  • now we want to add a column which contains the the first measurement in time
  • therefore we had to load plyr, then we use the function ddply() (the meaning of the first two letters is data frame in data frame out)
  • the first argument of the function is the data frame we pass to ddply
  • the second argument defines the groups (we want the min of each person so our grouping variable is id)
  • transform says we want to change existing data frame - like recode a variable or add a new (another choice would be summarise - if we want to aggregate the data) - so we add a variable named start and it should be the min() of our date per person
res <- ddply(df, .(id), transform, start=min(date))
res
iddatevalstart
12001-12-315.778679592025192001-03-07
12003-01-285.118336553288972001-03-07
12003-11-143.750754634375052001-03-07
12001-03-073.363050937734682001-03-07
12001-03-076.61415837892332001-03-07
22002-08-026.982798845791672000-05-29
22003-12-305.44500191386462000-05-29
22000-05-295.925679827166672000-05-29
22000-11-264.601699565975442000-05-29
22002-08-045.023958124582000-05-29
32002-04-235.925903245936592000-02-02
32003-04-286.592460569591672000-02-02
32002-10-205.897804643006622000-02-02
32000-02-024.05486188162692000-02-02
32000-05-305.47226334023782000-02-02
42000-08-033.527374580480372000-08-03
42002-11-023.988538941622852000-08-03
42002-11-134.543730885196552000-08-03
42003-08-024.21442451843462000-08-03
42003-12-194.987674782982792000-08-03
52002-08-295.239211212098212000-04-27
52000-04-274.204002414119612000-04-27
52003-07-266.18219572726462000-04-27
52003-05-184.535154046383622000-04-27
52001-07-233.066952749405012000-04-27
  • if we change the function just a little we get the days elapsed from the first measurment:
res <- ddply(df, .(id), transform, dayselapsed=date-min(date))
res
iddatevaldayselapsed
12001-12-315.77867959202519299
12003-01-285.11833655328897692
12003-11-143.75075463437505982
12001-03-073.363050937734680
12001-03-076.61415837892330
22002-08-026.98279884579167795
22003-12-305.44500191386461310
22000-05-295.925679827166670
22000-11-264.60169956597544181
22002-08-045.02395812458797
32002-04-235.92590324593659811
32003-04-286.592460569591671181
32002-10-205.89780464300662991
32000-02-024.05486188162690
32000-05-305.4722633402378118
42000-08-033.527374580480370
42002-11-023.98853894162285821
42002-11-134.54373088519655832
42003-08-024.21442451843461094
42003-12-194.987674782982791233
52002-08-295.23921121209821854
52000-04-274.204002414119610
52003-07-266.18219572726461185
52003-05-184.535154046383621116
52001-07-233.06695274940501452

Saturday, June 25, 2011

R - working with unique() and duplicated()

duplicated() vs. unique()

  • first we create a vector we can work with:
x <- sample(LETTERS[1:10], 20, replace=T)
x
 [1] "J" "C" "J" "C" "F" "J" "E" "J" "H" "A" "C" "G" "I" "A" "F" "H" "J" "C" "C"
[20] "D"
  • unique() gives us a vector containing every new element of x but ignores repeated elements
unique(x)
[1] "J" "C" "F" "E" "H" "A" "G" "I" "D"
  • duplicated() gives a logical vector
duplicated(x)
 [1] FALSE FALSE  TRUE  TRUE FALSE  TRUE FALSE  TRUE FALSE FALSE  TRUE FALSE
[13] FALSE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE FALSE
  • so if we want to get the same result like the one from unique we have to index x in the following way:
x[duplicated(x)==F]
[1] "J" "C" "F" "E" "H" "A" "G" "I" "D"
  • if we want to get just repeated occurences (i.e. a vector without the first occurence) we use the following line
x[duplicated(x)==T]
 [1] "J" "C" "J" "J" "C" "A" "F" "H" "J" "C" "C"
  • we can use these commands the same way on dataframes, so let our x code persons, and we add a numeric value which could be a measurement and the order of the vector describes the order in which the measurements are taken
y  <- rnorm(20, mean=10)
df <- data.frame(person=x, meas=y)
df
   person      meas
1       J 11.180452
2       C 10.235697
3       J 10.908622
4       C 10.677399
5       F  8.564007
6       J 10.070557
7       E 10.144191
8       J 10.872314
9       H 11.635032
10      A 10.448090
11      C 10.642052
12      G  8.689660
13      I 10.007930
14      A  8.321125
15      F 10.610739
16      H  9.060412
17      J 10.678726
18      C  8.513766
19      C  8.851564
20      D 12.793154
  • we extract the first measurement of each person with (the comma behind the F is important - it says we want the whole line)
df[duplicated(df$person)==F,]
   person      meas
1       J 11.180452
2       C 10.235697
5       F  8.564007
7       E 10.144191
9       H 11.635032
10      A 10.448090
12      G  8.689660
13      I 10.007930
20      D 12.793154
  • and with the following command we can extract the follow up measurements
df[duplicated(df$person)==T,]
   person      meas
3       J 10.908622
4       C 10.677399
6       J 10.070557
8       J 10.872314
11      C 10.642052
14      A  8.321125
15      F 10.610739
16      H  9.060412
17      J 10.678726
18      C  8.513766
19      C  8.851564
  • we also can use duplicate in a recursive way; the result of the following function is a list containing vectors whereupon the first contains the first occurence, the second the second, etc.; you can change it easily: so it can give back logical vectors which can use to index a dataframe, or for working on a dataframe itself (which both would be more useful)
sep.meas <- function(dupl){
  res <- list()
  while(length(dupl)>0){
    res[[length(res)+1] ] <- dupl[duplicated(dupl)==F]
    dupl <- dupl[duplicated(dupl)==T]
  }
 res
}
  • if we use it on x we get the following result
sep.meas(x)
[[1]]
[1] "J" "C" "F" "E" "H" "A" "G" "I" "D"

[[2]]
[1] "J" "C" "A" "F" "H"

[[3]]
[1] "J" "C"

[[4]]
[1] "J" "C"

[[5]]
[1] "J" "C"

R - sorting vectors: sort() vs. order()

sort() and order()

  • both operates on vectors and has the same aim, but the results are very different
First we create a vector we can sort:
x <- sample(LETTERS[1:10], 100, replace=T) # create a vector to sort by sampling from the first 10 Letters of the alphabet 100 times
x
  [1] "H" "D" "I" "E" "F" "B" "E" "G" "D" "A" "H" "I" "E" "A" "E" "A" "I" "J"
 [19] "I" "A" "B" "F" "A" "I" "F" "B" "A" "H" "J" "A" "E" "A" "C" "A" "A" "C"
 [37] "F" "C" "D" "G" "I" "I" "B" "J" "J" "D" "I" "J" "G" "J" "A" "B" "B" "C"
 [55] "A" "B" "D" "E" "D" "D" "E" "J" "A" "J" "G" "D" "A" "B" "D" "I" "F" "H"
 [73] "D" "J" "D" "E" "E" "A" "A" "J" "B" "E" "C" "I" "C" "F" "F" "E" "E" "J"
 [91] "H" "H" "F" "I" "A" "I" "H" "I" "I" "I"
  • the result of sort() is a vector consisting of elements of the original (unsorted) vector
sort(x)
  [1] "A" "A" "A" "A" "A" "A" "A" "A" "A" "A" "A" "A" "A" "A" "A" "A" "A" "B"
 [19] "B" "B" "B" "B" "B" "B" "B" "B" "C" "C" "C" "C" "C" "C" "D" "D" "D" "D"
 [37] "D" "D" "D" "D" "D" "D" "D" "E" "E" "E" "E" "E" "E" "E" "E" "E" "E" "E"
 [55] "E" "F" "F" "F" "F" "F" "F" "F" "F" "G" "G" "G" "G" "H" "H" "H" "H" "H"
 [73] "H" "H" "I" "I" "I" "I" "I" "I" "I" "I" "I" "I" "I" "I" "I" "I" "I" "J"
 [91] "J" "J" "J" "J" "J" "J" "J" "J" "J" "J"
  • if we do the same with order the result is completely different - we get a vector with the ordered indices of the original (unsorted) vector
order(x)
  [1]  10  14  16  20  23  27  30  32  34  35  51  55  63  67  78  79  95   6
 [19]  21  26  43  52  53  56  68  81  33  36  38  54  83  85   2   9  39  46
 [37]  57  59  60  66  69  73  75   4   7  13  15  31  58  61  76  77  82  88
 [55]  89   5  22  25  37  71  86  87  93   8  40  49  65   1  11  28  72  91
 [73]  92  97   3  12  17  19  24  41  42  47  70  84  94  96  98  99 100  18
 [91]  29  44  45  48  50  62  64  74  80  90
  • if you want to get the ordered vector (like with sort()) you have to index the original vector with the vector of the indices
x[order(x)]
  [1] "A" "A" "A" "A" "A" "A" "A" "A" "A" "A" "A" "A" "A" "A" "A" "A" "A" "B"
 [19] "B" "B" "B" "B" "B" "B" "B" "B" "C" "C" "C" "C" "C" "C" "D" "D" "D" "D"
 [37] "D" "D" "D" "D" "D" "D" "D" "E" "E" "E" "E" "E" "E" "E" "E" "E" "E" "E"
 [55] "E" "F" "F" "F" "F" "F" "F" "F" "F" "G" "G" "G" "G" "H" "H" "H" "H" "H"
 [73] "H" "H" "I" "I" "I" "I" "I" "I" "I" "I" "I" "I" "I" "I" "I" "I" "I" "J"
 [91] "J" "J" "J" "J" "J" "J" "J" "J" "J" "J"

Sunday, June 5, 2011

R - Recoding (missing) values in a matrix

let v be a vector
> v <- c(1,2,4,99,6,999,7,8,99,5,2,4,9,2)

where the missing values where coded as 9, 99 or 999.

Then the fastest way (i know) to recode them is:

> v[v %in% c(9,99,999)] <- NA

> v
[1] 1 2 4 NA 6 NA 7 8 NA 5 2 4 NA 2

an example with matrices:
> m <- matrix(1:12, nrow=3, byrow=T,dimnames = list(letters[1:3],LETTERS[1:4])) > m
A B C D
a 1 2 3 4
b 5 6 7 8
c 9 10 11 12
> m[m %in% c(9,99,999)] <- NA

> m
A B C D
a 1 2 3 4
b 5 6 7 8
c NA 10 11 12

This does not work on dataframes. You have to operate on each column separately. If you have many columns maybe it is worth a try to load the package epicalc or lordif and use the command recode() or you do it in loop ...