Create a list from a complex comparison of two lists

Viewed 57

I am working on market transaction data where each observation contains the value of the variable of the buyer's id, and the value of the variable of the seller's id. For each observation (i.e each transaction), I would like to create a variable equal to the number of other transactions the associated seller has done with a different buyer than the one involved in this transaction. As a consequence, in the following

data <- data.frame(Buyer_id = c("001","001","002","001"), Seller_id = c("021","022","022","021"))

I would like to obtain:

Result <- list(0,1,1,0)

I searched for already existing answers for similar problems than mine, usually involving the function mapply(), and tried to implement them, but it proved unsuccessful.

Thank you very much for helping me.

2 Answers

Are you looking for something like this? If yes, then you might want to change your reproducible example to have a c instead of list when you construct your data.frame.

data <- data.frame(Buyer_id = c("001","001","002","001"), 
                   Seller_id = c("021","022","022","021"))

data$n <- NA
for (i in seq_len(nrow(data))) {
  seller <- as.character(data[i, "Seller_id"])
  buyer <- as.character(data[i, "Buyer_id"])
  
  with.buyers <- as.character(data[data$Seller_id == seller, "Buyer_id"])
  with.buyers <- unique(with.buyers)
  
  diff.buyers <- with.buyers[!(with.buyers %in% buyer)]
  
  data[i, "n"] <- length(diff.buyers)
}

  Buyer_id Seller_id n
1      001       021 0
2      001       022 1
3      002       022 1
4      001       021 0

Apart from Roman Lustrik's solution, there is also an approach that uses graphs.

library(igraph)

data <- data.frame(Seller_id = c("021","022","022","021"),
                   Buyer_id = c("001","001","002","001"),
                   stringsAsFactors = FALSE)

my.graph <- graph_from_data_frame(data)
plot(my.graph)
degree(my.graph, mode = c("out"))

# Transform the graph into a simple graph. A simple graph does not allow
# duplicate edges.
my.graph <- simplify(my.graph)
plot(my.graph)
degree(my.graph, mode = c("out"))

V(my.graph)$out.degree <- degree(my.graph, mode = c("out"))

data$n <- apply(data,
                MARGIN = 1,
                FUN = function(transaction)
                {
                  node.out.degree <- V(my.graph)$out.degree[ V(my.graph)$name == transaction["Seller_id"] ]
                  
                  if (node.out.degree <= 1) {
                    # Since the vertex has at most 1 out degree we know that the current transaction
                    # is the only appearance of the current seller.
                    return(0)
                  } else {
                    # In this case, we know that the seller participates in at least one more
                    # tansaction. We therefore simply subtract minus one (the current transaction)
                    # from the out degree.
                    return(node.out.degree - 1)
                  }
                  
                })

data
Related