dplyr -- tidyverse, pipes, correlation, same variable across time "a" "b" Have a look at this dataset. The"a" and "b" are used to make possible differentiate when the same variable was measured. In this case X1a and X1b access the same variable, but "a" was (suppose..) in the last year and "b" was this year. 


I just want to correlate "a" and "b" and plot it. Simple like that and I really imagine the following code can be improved. 

The final plot will be this one:

The data is fake, but it's virtually equal as the original dataset I'm working on.

 all_items &lt;- data.frame("1a" = sample(1:5), 
                            "2a" = sample(1:5),
                            "3a" = sample(1:5),
                            "1b" = sample(1:5),
                            "2b" = sample(1:5),
                            "3b" = rep(sample(1:5),10))


    #matrix with correlation
    all_correlation &lt;- cor(all_items, method = "spearman") %&gt;% 
      as.data.frame()

    #filter
    all_correlation &lt;- all_correlation %&gt;% select(-c(ends_with("a"))) #columns

    #create a colum with the now name
    all_correlation &lt;- all_correlation %&gt;% 
      mutate(item = row.names(.)) %&gt;% select(item, everything())

    #supress some rows
    all_correlation &lt;- all_correlation %&gt;%  filter(!grepl("b", item))

    #filter(stringr::str_detect(row.names(.), "b"))
    #get only the diagonal
    all_correlation &lt;- data.frame(item=1:3,Result=diag(as.matrix(all_correlation[, -1])))

    #P Value
    all_correlation_p_value &lt;- Hmisc::rcorr(as.matrix(all_items))$P %&gt;% as.data.frame()

    #filter
    all_correlation_p_value &lt;- all_correlation_p_value %&gt;% select(-c(ends_with("a")))
    all_correlation_p_value &lt;- all_correlation_p_value %&gt;% mutate(item = row.names(.)) %&gt;% select(item, everything())
    all_correlation_p_value &lt;- all_correlation_p_value %&gt;%  filter(!grepl("b", item))
    all_correlation_p_value &lt;- data.frame(item=1:3,P_Valor=diag(as.matrix(all_correlation_p_value[, -1])))

    #General table with the correlation  results
    all_correlation &lt;- right_join(all_correlation,all_correlation_p_value, by = "item")


#Plot
ggplot(all_correlation, aes(x=item, y=Result)) + 
  geom_point(aes(color=Result)) +
  geom_line() +
  annotate("text", x = all_correlation$item, 
           y=all_correlation$Result, 
           label = paste("P-value =",round(all_correlation$P_Valor,3)), hjust = -0.1, colour = "red") +
  scale_x_continuous(breaks = seq(1,3,1))
Here are two possible rewrites. For the first one, notice how Hmisc::rcorr already computes correlations ($r) and p-values ($P) matrices so you can base all your work from it, provided you extract the rights rows (a_vars) and columns (b_vars) and only keep the diagonal values:

correlations &lt;- rcorr(as.matrix(all_items), type = "spearman")
a_vars &lt;- ends_with("a", vars = names(all_items))
b_vars &lt;- ends_with("b", vars = names(all_items))
all_correlation &lt;- data.frame(
  item    = seq_along(a_vars),
  Result  = diag(correlations$r[a_vars, b_vars]),
  P_Valor = diag(correlations$P[a_vars, b_vars])
)


What I don't like too much about this approach is that it only uses 3 of the 36 correlations that were computed by rcorr. In this second approach, I start by splitting the data into two tables (one for a and one for b) so as to compute only 3 correlations via Map. I also switched from rcorr to the base cor.test which has (IMO) a more intuitive behavior: when given two vectors as input, it computes one correlation, not four.

a &lt;- all_items %&gt;% select(ends_with("a"))
b &lt;- all_items %&gt;% select(ends_with("b"))
cor_test &lt;- Map(cor.test, a, b)
all_correlation &lt;- data.frame(
  item    = seq_along(a),
  Result  = sapply(cor_test, `[[`, "estimate"),
  P_Valor = sapply(cor_test, `[[`, "p.value")
)