2

I have a question that seems simple, but I can't seem to find an answer to this problem. I am trying to replace all values generated in a williams design (values 1 - 4) with a character string TRT1, TRT2, etc.

d = data.frame(crossdes::williams(4))
names(d) = c("Period 1", "Period 2","Period 3","Period 4")
d2 = data.frame(treatmentNo = c(1,2,3,4), 
            treatmentName = c("TRT1","TRT2",
                              "TRT3", "TRT4"))

I would like to have everything in d changed from values to what is specified in d2.

Thanks.

maj
  • 2,479
  • 1
  • 19
  • 25
David S
  • 193
  • 11
  • Just out of interest: Which package is the `williams()` function from? – maj Jun 05 '15 at 14:05
  • Apologies - it is from the crossdes package. It just creates a williams design crossover (in this case, just a latin square). It results in a 4x4 matrix. – David S Jun 05 '15 at 14:06
  • Just to clarify, so if its 1, it should be replaced by TRT1, if its 2, it should be replaced by TRT2 and so on? – ytk Jun 05 '15 at 14:09
  • have tried with [?gsub](https://stat.ethz.ch/R-manual/R-devel/library/base/html/grep.html) – Mitra Jun 05 '15 at 14:10
  • Teja K - You are correct. Mitra - I thought about gsub, but I am not sure how to use this to replace a vector of numbers (1 - 4) with a vector of replacments (TRT1 - TRT4) in a data frame. – David S Jun 05 '15 at 14:12
  • 1
    you can easily embed it in a function as [lapply](https://stat.ethz.ch/R-manual/R-devel/library/base/html/lapply.html) – Mitra Jun 05 '15 at 14:14
  • I've made a very quick research on SO, and come up with this Q: http://stackoverflow.com/questions/6954017/r-replace-characters-using-gsub-how-to-create-a-function . (Though, the accepted answer uses `for` which I personally hate using in R) I am sure they are plenty others – Mitra Jun 05 '15 at 14:17
  • 1
    Or this Q: http://stackoverflow.com/questions/16540305/replace-string-in-dataframe – maj Jun 05 '15 at 14:20
  • 1
    When you say 'everything in d' what are you referring to? d2 has two columns, 4 rows. d has 4 columns. Does it have 2 rows? Will d2 values be repeated across the entire d data frame? Are you just changing the names? You did not post the desired output for comparison or testing. – Pierre L Jun 05 '15 at 14:49

2 Answers2

1

You could do:

library(dplyr)
d %>% mutate_each(funs(d2$treatmentName[match(.,d2$treatmentNo)]))

Which gives:

#  Period 1 Period 2 Period 3 Period 4
#1     TRT1     TRT2     TRT4     TRT3
#2     TRT2     TRT3     TRT1     TRT4
#3     TRT3     TRT4     TRT2     TRT1
#4     TRT4     TRT1     TRT3     TRT2

Or you could also try the lookup() function in the qdapTools package:

library(qdapTools)
data.frame(apply(d, 2, lookup, d2))

Or using base R:

data.frame(lapply(d, function(x) d2$treatmentName[match(x, d2$treatmentNo)]))

Which gives:

#  Period.1 Period.2 Period.3 Period.4
#1     TRT1     TRT2     TRT4     TRT3
#2     TRT2     TRT3     TRT1     TRT4
#3     TRT3     TRT4     TRT2     TRT1
#4     TRT4     TRT1     TRT3     TRT2
Tyler Rinker
  • 108,132
  • 65
  • 322
  • 519
Steven Beaupré
  • 21,343
  • 7
  • 57
  • 77
  • Thanks Steven, both seem to work. It's a bit surprising though that it involves downloading and installing some fairly extensive packages to do something so simple. I would have though some apply function would have worked. This works great, however. – David S Jun 05 '15 at 15:47
0

A solution with no external packages

f <- function(x) x[match(x,d2[,1])] <- d2[match(x,d2[,1]),2]

newdf <- apply(d,1,f)

newdf <- t(newdf)
RDGuida
  • 546
  • 4
  • 15
  • Thanks - this seems good too, except that it wipes out the data frame, requiring it to be recreated. This is fine, it just changes the order of how I would create the data frame. – David S Jun 05 '15 at 16:27