I want to convert a dataframe from wide format to long format.
Here it is a toy example:
mydata <- data.frame(ID=1:5, ZA_1=1:5,
ZA_2=
You can melt several columns simultaneously, if you pass a list of column names to the argument measure =
. One approach to do this in a scalable manner would be to:
Extract the column names and the corresponding first two letters:
measurevars <- names(mydata)[grepl("_[1-9]$",names(mydata))]
groups <- gsub("_[1-9]$","",measurevars)
Turn groups
into a factor object and make sure levels aren't ordered alphabetically. We'll use this in the next step to create a list object with the correct structure.
split_on <- factor(groups, levels = unique(groups))
Create a list using measurevars
with split()
, and create vector for the value.name =
argument in melt()
.
measure_list <- split(measurevars, split_on)
measurenames <- unique(groups)
Bringing it all together:
melt(setDT(mydata),
measure = measure_list,
value.name = measurenames,
variable.name = "measure")
# ID measure ZA BB
# 1: 1 1 1 3
# 2: 2 1 2 3
# 3: 3 1 3 3
# 4: 4 1 4 3
# 5: 5 1 5 3
# 6: 1 2 5 6
# 7: 2 2 4 6
# 8: 3 2 3 6
# 9: 4 2 2 6
#10: 5 2 1 6