【问题标题】:Co-occurrences from a large dataframe来自大型数据帧的共现
【发布时间】:2017-01-19 07:43:19
【问题描述】:

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

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 个用户的 150 万次访问日志的大型数据集,table 命令会报错:

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

那么,我怎样才能在不耗尽内存的情况下获得共同访问边缘?

【问题讨论】:

  • 也许,尝试一个稀疏的替代方案 -- crossprod(sparseMatrix(i = as.integer(df.visited$city), j = as.integer(df.visited$user), x = 1L, dimnames = rev(sapply(df.visited, levels))))

标签: r


【解决方案1】:

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

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

这是我看到的步骤:

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

如果您想更清楚地了解 #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)

【讨论】:

  • 感谢 Hack-R。但是我想在 R (igraph) 中使用图表,因为我想应用一些算法,例如社区检测。
  • @alberto 软件包页面上有关于如何使用igraphRneo4J 的说明。是这样的library(igraph); query = " MATCH (n)--&gt;(m) RETURN n.name, m.name "; edgelist = cypher(graph, query); ig = graph.data.frame(edgelist, directed=F); betweenness(ig); plot(ig)
【解决方案2】:

试试这个来避免表函数。

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

【讨论】:

  • 谢谢盛林。但不幸的是Error: cannot allocate vector of size 288.3 Gb 我认为我们应该避免使用正则矩阵。
【解决方案3】:

说到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 是您可能正在(?)寻找的图表。

【讨论】:

  • 差不多了:At vector.pmt:439 : cannot reserve space for vector, Out of memory 但看起来我可以释放一些内存或在小型服务器上运行它。我明天试试,但我想我会给你送些啤酒。
  • 顺便说一句,最后一行是 as.data.frame(g2, "edges") %&gt;% head Error in as.data.frame.default(g2, "edges") : cannot coerce class ""igraph"" to a data.frame 您使用的是哪个 igraph 版本?
  • 我正在使用packageVersion("igraph") ‘1.0.1’。啤酒总是受欢迎的:-)
猜你喜欢
  • 1970-01-01
  • 2020-12-15
  • 2021-01-02
  • 1970-01-01
  • 2020-08-05
  • 2011-08-17
  • 2013-12-10
  • 1970-01-01
  • 2022-08-05
相关资源
最近更新 更多