从两个列表的复杂比较中创建一个列表

Create a list from a complex comparison of two lists

我正在处理市场交易数据,其中每个观察值都包含买方 ID 变量的值和卖方 ID 变量的值。对于每次观察(即每笔交易),我想创建一个变量,该变量等于关联卖家与与此交易中涉及的买家不同的买家完成的其他交易的数量。因此,在下面

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

我想获得:

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

我搜索了与我的类似问题的现有答案,通常涉及函数 mapply(),并尝试实现它们,但未成功。

非常感谢你帮助我。

您正在寻找这样的东西吗?如果是,那么您可能希望在构建 data.frame.

时将可重现的示例更改为 c 而不是 list
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

除了 Roman Lustrik 的解决方案之外,还有一种使用图表的方法。

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