来自大型数据帧的共现

时间:2016-09-11 21:07:35

标签: r

我有一个数据框,其中包含有关哪些城市访问过每个用户的信息:

df.visited <- data.frame(user  = c("john","john", 
                                   "claire", "claire", 
                                    "doe","doe"), 
                        city = c('Antananarivo', 'Barcelona', 
                                 'Caen', 'Dijon', 
                                 'Antananarivo', 'Caen'))

我想创建一个共同访问的图表。为此,我需要一个邻接矩阵(用户x用户)或边缘列表(usera,userb,#co-visits)

我可以为小型数据集执行此操作:

by_user_city <- table(df.visited)    

#        city
#user     Antananarivo Barcelona Caen Dijon
#claire            0         0    1     1
#doe               1         0    1     0
#john              1         1    0     0

adjacency <- by_user_city %*% t(by_user_city)

#     user 
#user     claire doe john
#claire      2   1    0
#doe         1   2    1
#john        0   1    2

edges <- melt(adjacency)

#    user   user value
#1 claire claire     2
#2    doe claire     1
#3   john claire     0
#4 claire    doe     1
#5    doe    doe     2
#6   john    doe     1
#7 claire   john     0
#8    doe   john     1
#9   john   john     2

对于记录超过300,000个用户的1.5M访问记录的大型数据集,table命令会抱怨:

Error in table(df.visited) : 
  attempt to make a table with >= 2^31 elements

那么,如何在不耗尽内存的情况下获得共同访问边缘?

3 个答案:

答案 0 :(得分:3)

鉴于您的数据大小,我建议您使用Java图形数据库neo4j。前neo4j员工Nicole White为它制作了一个R包,RNeo4j。我在2014年这样做是为了在一个非常大的公司社交网络上建立大量的实时分析,并且它运作良好。

您也可以使其与其他图形数据库一起使用,但这是我所知道的,我认为它可能是最受欢迎的。

以下是我看到的步骤:

  1. Download Neo4j
  2. install.packages("RNeo4j")
  3. 连接: graph = startGraph("http://localhost:7474/db/data/")
  4. 使用transactional endpoint加载数据
  5. 使用Cypher
  6. 查询结果

    如果你想更清楚#4和#5那里有old post,有人问如何扩大使用R将数据加载到neo4j,其中White回答了如何使用事务端点的示例并查询结果。当然,如果你愿意,也可以在R之外加载它。

    这也解决了您可能对社交图形进行可视化,对网络/论坛进行各种不同查询,处理不断增加的大小等等未来的许多问题。您不应该遇到内存这种方式存在问题,因为它非常适合规模化。

    您可以使用igraphggnet之类的图形包,将内存密集型部分保留在图形数据库中:

    library(igraph)
    
    query = "
    MATCH (n)-->(m)
    RETURN n.name, m.name
    "
    
    edgelist = cypher(graph, query)
    ig = graph.data.frame(edgelist, directed=F)
    
    betweenness(ig)
    
    plot(ig)
    

    enter image description here

答案 1 :(得分:2)

尝试这样做以避免表格功能。

library(tidyr)
df.visited$val<-1
spread(df.visited,city,val,fill=0)

答案 2 :(得分:2)

说到igraph - 也许可以试试:

library(igraph)
g <- graph_from_data_frame(df.visited)
V(g)$type <- bipartite.mapping(g)$type
g2 <- bipartite.projection(g)$proj1
as_data_frame(g2, "edges") %>% head
#     from  to weight
# 1   john doe      1
# 2 claire doe      1

g2是您可能(?)寻找的图表。