0

我有一个非常大的数据集,其中包含 3 列兴趣、id、house 和 people。每个 id 可以有多个房子,每个房子可以有多个人。我想使用@David Arenburg 在此处共享的内容创建边缘列表在 R 中创建带有其他变量的边缘列表

但是,我遇到的问题是给出的边缘是“a;b”和“b;a”。我只想拥有它们一次。由于 a 和 b 的大集合可以产生数千个 a;b, b;a 组合。

我只想拥有它们一次,因为我想计算人们共享房屋的次数。

给定数据集

id=c(rep("ID1",3), rep("ID2",6), "ID3", rep("ID4",5))
house=c(rep("house1",2), "house2", rep("house3",2), rep("house4",4), "house5", rep("house6",3), "house7", "house8")
people=c("a","b","c","d","e","d","e","d","e","f","g","h","h","h","h")

df1 <- data.frame(id,house, people)

@David Arenburg 的以下代码为我们提供了边缘列表

df1 = setDT(df1)[, if(.N > 1) tstrsplit(combn(as.character(people),
              2, paste, collapse = ";"), ";"),
            .(id, house)]

结果

     id  house V1 V2
 1: ID1 house1  a  b
 2: ID2 house3  d  e
 3: ID2 house4  d  e
 4: ID2 house4  d  d
 5: ID2 house4  d  e
 6: ID2 house4  e  d
 7: ID2 house4  e  e
 8: ID2 house4  d  e
 9: ID4 house6  g  h
10: ID4 house6  g  h
11: ID4 house6  h  h

正如你所看到的,在 V1 和 V2 之间,房子有两个 'd;e','e;d' 我想避免。因此,对于大量数据,这些组合可能在 1000 秒内

谢谢你的帮助

4

2 回答 2

1

我确信有一种更简洁的基本 R 方法,但这是一种dplyr方法,我们对两个值进行排序以更容易消除重复。

library(dplyr)
df %>%
  mutate(V1s = if_else(V1 < V2, V1, V2),
         V2s = if_else(V1 < V2, V2, V1)) %>%
  distinct(id, house, V1s, V2s)
于 2019-09-13T03:36:58.557 回答
0

@David Aremburg 提供的出色答案有可能产生。

总体策略:

  1. 使用有序边创建一个新变量(即,将“e -> d”转换为“d -> e”)
  2. 获取id,house和新变量的每个组合的唯一值。
  3. 删除变量

.

library(data.table)

# keep Aremburg's solution and chain a couple of additional commands:
setDT(df1)[, 
           if(.N > 1) tstrsplit(combn(as.character(people),
                                      2, paste, collapse = ";"), ";"),
            .(id, house)][, 
                         edge := apply(.SD, 
                                       1, 
                                       function(x) paste(sort(c(x[1], 
                                                                x[2])), 
                                                         collapse = ",")), 
                         .SDcols = c("V1", "V2")][, 
                                                  .SD[1, ], 
                                                  by = .(id, house, edge)][
                                    , edge := NULL][]

    id  house V1 V2
1: ID1 house1  a  b
2: ID2 house3  d  e
3: ID2 house4  d  e
4: ID2 house4  d  d
5: ID2 house4  e  e
6: ID4 house6  g  h
7: ID4 house6  h  h

请注意,您也可以删除其中的行V1 == V2,因为它们是不相关的边缘。这可以[V1 != V2, ]在前一个链的末端完成。

于 2019-09-13T04:26:19.543 回答