0

I have a tibble with the following format:

ID       fragment1   value1   fragment2   value2   fragment3   value3
1        50          90       45          10       NA          NA
2        50          100      NA          NA       NA          NA

I want to make a barplot "fragment vs value" but I can't find the right way to modify the original matrix and I am struggling a bit to wrap my head around the "melting data" concept (by which I mean I don't completely understand what I should be aiming for). Any help would be much appreciated.

jay.sf
  • 60,139
  • 8
  • 53
  • 110
point618
  • 1,309
  • 2
  • 10
  • 23

2 Answers2

4

reshape it on a list of the two column subsets, transpose, and barplot it.

reshape(dat, idvar='ID', varying=list(c(2, 4, 6), c(3, 5, 7)), direction='long') |>
  subset(select=3:4) |> t() |> barplot(beside=TRUE)

enter image description here

----

Update: Inspired by a comment from @onyambu, we can write the call a little golfy:

barplot(t(reshape(dat, -1, di='l', se='')[3:4]), be=T)

where

reshape(dat, -1, di='l', se='')
#     ID time fragment value id
# 1.1  1    1       50    90  1
# 2.1  2    1       50   100  2
# 1.2  1    2       45    10  1
# 2.2  2    2       NA    NA  2
# 1.3  1    3       NA    NA  1
# 2.3  2    3       NA    NA  2

Data:

dat <- structure(list(ID = 1:2, fragment1 = c(50L, 50L), value1 = c(90L, 
100L), fragment2 = c(45L, NA), value2 = c(10L, NA), fragment3 = c(NA, 
NA), value3 = c(NA, NA)), class = "data.frame", row.names = c(NA, 
-2L))
jay.sf
  • 60,139
  • 8
  • 53
  • 110
  • 1
    you can use the `sep` argument: `reshape(dat, -1, dir='long', sep=''")` and should work. Or even use the `split` argument. Note that i have not specified the `idvar` you can do so in order not to duplicate the `id` – Onyambu Jul 15 '22 at 17:06
  • @onyambu Amazing! I was surprised an `id` appeared, how come? Never used the `split` argument so far, unfortunately, the masters of `reshape` appear to be rather silent ;) – jay.sf Jul 15 '22 at 17:24
3

Update: Thanks to @r2evans:

No need for rename_with:

library(dplyr)
library(tidyr)

pivot_longer(df, -ID, names_pattern = "(.*)([0-9]+)$", names_to = c(".value", "group"))

First answer: Something like this:

library(dplyr)
library(tidyr)

df %>% 
  rename_with(., ~sub("(\\d)$", "_\\1", .)) %>% 
  pivot_longer(
    -ID,
    names_to = c(".value", "group"),
    values_to = "value",
    names_sep = "\\_"
  )
 ID group fragment value
  <int> <chr>    <int> <int>
1     1 1           50    90
2     1 2           45    10
3     1 3           NA    NA
4     2 1           50   100
5     2 2           NA    NA
6     2 3           NA    NA
TarJae
  • 72,363
  • 6
  • 19
  • 66
  • 2
    No need to `rename_with`, could just use `pivot_longer(dat, -ID, names_pattern = "(.*)([0-9]+)$", names_to = c(".value", "group"))` (though perhaps that's just code-golf). – r2evans Jul 15 '22 at 16:02
  • 1
    @r2evans. Thank you I will add this to my answer! – TarJae Jul 15 '22 at 19:36