0

I want view the variables of interest (height,weight and BP) according to their visits in a horizontal manner.

This is the original dataset:

attempt = data.frame( ID = c(rep("S1",3),rep("S2",3)),
             visit = rep(seq(1:3),2),
             height = c(154,155,156,150,152,158),
             weight = c(54,56,57,60,62,70),
             BP = c(140,120,160,170,180,190))

original data

original data

I tried the reshape command below but the output looks strange.

data2 <- reshape(attempt, timevar="visit", idvar="ID", direction="wide")

after reshape command

after reshape command

Any ideas on why my output does not show? Thanks

My desired output for the column heading is:

ID height.1 height.2 height.3 weight.1 weight.2 weight.3 BP.1 BP.2 BP.3

I want each ID's height, weight and BP to be sorted based on their visits in horizontal columns.

A. Suliman
  • 12,923
  • 5
  • 24
  • 37
racergeek
  • 1
  • 2

3 Answers3

2

Using the dcast() from the data.table-package, this becomes pretty straightforward:

library(data.table)
#make a data.table out of 'attempt'
data.table::setDT(attempt)
#cast to desired wide format
data.table::dcast( attempt,
                   ID ~ visit,
                   value.var = c( "height", "weight", "BP" ) )

#    ID height_1 height_2 height_3 weight_1 weight_2 weight_3 BP_1 BP_2 BP_3
# 1: S1      154      155      156       54       56       57  140  120  160
# 2: S2      150      152      158       60       62       70  170  180  190
Wimpel
  • 26,031
  • 1
  • 20
  • 37
1

Hi and welcome to StackOverflow !

So, here is a solution, I doubt that it is a perfect solution but it is doing the job, here what you can do:

attempt = reshape(attempt, idvar = "ID", direction = "wide", v.names = c("height","weight","BP"), timevar = "visit")

attempt = attempt[,c("ID",colnames(attempt)[grep("height",colnames(attempt))],
             colnames(attempt)[grep("weight",colnames(attempt))],
             colnames(attempt)[grep("BP",colnames(attempt))])]

And here is the output:

> attempt
  ID height.1 height.2 height.3 weight.1 weight.2 weight.3 BP.1 BP.2 BP.3
1 S1      154      155      156       54       56       57  140  120  160
4 S2      150      152      158       60       62       70  170  180  190

As I said, this solution is definitely not the best but the best to my current knowledge. Most likely more experienced R coders will be able to show up with a nicer and more elegant solution ;)

dc37
  • 15,840
  • 4
  • 15
  • 32
0

Base R solution slightly amending your code:

Should do the trick (worked for me):

data2 <- data.frame(reshape(attempt, timevar="visit", idvar="ID", direction="wide"), stringsAsFactors = F)

But just incase:

data2 <- setNames(data2, gsub("[[:punct:]]|\\s+", ".", trimws(names(data2), "both")))

Data:

attempt <-
  structure(
    list(
      ID = structure(
        c(1L, 1L, 1L, 2L, 2L, 2L),
        .Label = c("S1",
                   "S2"),
        class = "factor"
      ),
      visit = c(1L, 2L, 3L, 1L, 2L, 3L),
      height = c(154, 155, 156, 150, 152, 158),
      weight = c(54,
                 56, 57, 60, 62, 70),
      BP = c(140, 120, 160, 170, 180, 190)
    ),
    class = "data.frame",
    row.names = c(NA,-6L)
  )
hello_friend
  • 5,682
  • 1
  • 11
  • 15