I have a dataset which contains count data where the structure looks like:
Sample | ID | Expected | Observed_A | Observed_B |
---|---|---|---|---|
A | id1 | 10 | 8 | 10 |
A | id2 | 6 | 8 | 4 |
B | id1 | 15 | 12 | 18 |
B | id2 | 1 | 2 | 4 |
What I'm trying to get to with tidyr/dplyr is the per-sample correlation between each of the observed counts and the expected counts (i.e. I'm unfussed by the correlation between each of the observed columns).
Sample | Dataset | Correlation |
---|---|---|
A | Observed_A | 0.99 |
A | Observed_B | 0.93 |
B | Observed_A | 0.89 |
B | Observed_B | 0.91 |
I can do this by looping, but was wondering whether there is a 'clearer' approach to take using tidyverse functions?
Any help much appreciated!!
CodePudding user response:
How about this:
library(dplyr)
#>
#> Attaching package: 'dplyr'
#> The following objects are masked from 'package:stats':
#>
#> filter, lag
#> The following objects are masked from 'package:base':
#>
#> intersect, setdiff, setequal, union
library(tidyr)
d <- tibble::tribble(~Sample, ~ID, ~Expected, ~Observed_A, ~Observed_B,
"A", "id1", 10, 8, 10,
"A", "id2", 6, 8, 4,
"B", "id1", 15, 12, 18,
"B", "id2", 1, 2, 4)
d %>%
group_by(Sample) %>%
summarise(as.data.frame(cor(Expected, cbind(Observed_A, Observed_B)))) %>%
pivot_longer(-Sample, names_to = "Dataset", values_to="Correlation")
#> Warning in cor(Expected, cbind(Observed_A, Observed_B)): the standard deviation
#> is zero
#> # A tibble: 4 × 3
#> Sample Dataset Correlation
#> <chr> <chr> <dbl>
#> 1 A Observed_A NA
#> 2 A Observed_B 1
#> 3 B Observed_A 1
#> 4 B Observed_B 1
Created on 2022-03-04 by the reprex package (v2.0.1)
CodePudding user response:
df %>%
group_by(Sample) %>%
summarize(across(Observed_A:Observed_B, ~cor(.x, Expected))) %>%
pivot_longer(!Sample, values_to = "Correlation", names_to = "Dataset")