Joshua Rosenberg Joshua Rosenberg - 1 month ago 6
R Question

Create data.frame for each connection between identifier in vector and from list (of vectors) in R

I have network data that consists of two columns, the first, a

sender
identifier, a
vector
of length
1
and the second, a
receiver
identifier, which is a
vector
of length
1
or more. This is the tricky part, the idea is each
sender
can connect with one or more
receiver
.

I am trying to create a
data.frame
with two columns, one for
sender
and one for
receiver
, with each pairwise connection. Here is the goal for what the final data should look like:

output <-
data.frame(sender = c("person_1", c("person_2", "person_2"), "person_3", c("person_4", "person_4"), "person_5"),
receiver = c("person_6", c("person_7", "person_8"), "person_9", c("person_10", "person_11"), "person_12"))

> output
sender receiver
1 person_1 person_6
2 person_2 person_7
3 person_2 person_8
4 person_3 person_9
5 person_4 person_10
6 person_4 person_11
7 person_5 person_12


Here is the data:

sender <- paste("person_", 1:5, sep = "")
receiver <- list("person_6", c("person_7", "person_8"), "person_9", c("person_10", "person_11"), "person_12")

> str(sender)
chr [1:5] "person_1" "person_2" "person_3" "person_4" "person_5"

> str(receiver)
List of 5
$ : chr "person_6"
$ : chr [1:2] "person_7" "person_8"
$ : chr "person_9"
$ : chr [1:2] "person_10" "person_11"
$ : chr "person_12"

Answer

One way would be to add sender names to relevant entries in the receiver list and then use the oddly-named function stack:

res0 = stack(setNames(receiver, sender))[, 2:1]

The names in the result are weird, so you might want to change them

res = setNames(res0, c("sender", "receiver"))

    sender  receiver
1 person_1  person_6
2 person_2  person_7
3 person_2  person_8
4 person_3  person_9
5 person_4 person_10
6 person_4 person_11
7 person_5 person_12

This matches the OP's output object apart from column classes.


I would probably use magrittr for readability here instead of the code above:

library(magrittr)
receiver %>% setNames(sender) %>% stack %>% rev %>% setNames(c("sender", "receiver"))

Alternately (and I don't want to recommend this...):

library(tidyr)
library(tibble)
data_frame(sender, receiver) %>% unnest(receiver)