GraphGists

在社交网络中寻找影响者

简介

对于这个 Graph Gist,我将分析社交网络用户(如 Twitter 或 Facebook)之间的互动。

许多使用社交网络的示例侧重于朋友和推荐,我将重点关注人们如何使用网络,并尝试建立不同类型的行为并寻找影响者。这很重要,因为作为社交网络的所有者,您想知道哪些是核心用户,或者作为用户,想知道哪些人值得关注。您还可以利用它来识别在电子商务网站上通过评论具有影响力的购物者。

模型

我的图模型如下所示

social model
图 1. Alice 有多受欢迎?

节点

User:社交网络的用户。

Message:消息在User`s 之间发送,并与其他 `Message`s 存在 `FORWARD` 和 `REPLY_TO` 关系。

关系

FOLLOWS:`User`s 关注其他 `User`s。

SENT:`User`s 将 `Message`s 发送给其他 `User`s

FORWARD:一个 `Mesage` 可能是另一个 `Message` 的转发版本

REPLY_TO:一个 `Message` 可能是对另一个 `Message` 的回复

设置

用例:列出所有用户和消息

为了分析,让我们从简单地列出所有 `User`s 和 `Message`s 开始

MATCH path=(User)-[:SENT]->(Message)
RETURN path

如您所见,很难从这种视图中发现任何模式。

用例:查找用户数量

请记住,我们的目标是找到网络中的影响者,我们可以从最简单的指标开始,即关注某个用户的用户数量。

MATCH (follower:User)-[:FOLLOWS]->(targetUser:User)-[:FOLLOWS]->(following:User)
RETURN targetUser AS User, COUNT(distinct follower) AS Followers, COUNT(distinct following) AS Following

为了获得更多信息,我们可以提供所有关注者的姓名

MATCH (p:User)-[f:FOLLOWS]->(p1:User)
RETURN p.id AS User, COLLECT(p1.id) AS Following

虽然这很有趣,但它并不能告诉我们太多关于用户行为的信息。他们可能不活跃,或者他们可能每天发送多条消息。

我们可以轻松地使用以下查询查看用户活跃度

MATCH (p:User)-[:SENT]->(tweet:Message)
RETURN p.id AS User, COUNT(tweet) AS Tweets

现在我们可以了解用户的活跃程度,但让我们深入研究并查看他们的活动类型。

用例:转发消息作为影响力的衡量标准

衡量影响力的一个指标是用户的消息在整个网络中被转发的频率,因此让我们找到转发次数最多的消息

MATCH (retweet:Message)-[r:FORWARD]->(tweet:Message)
RETURN tweet, COUNT(r)
ORDER BY COUNT(r) DESC

我们可以通过限制我们查看的消息来限制到特定的一天

MATCH (retweet:Message)-[r:FORWARD]->(tweet:Message {day_sent:'Monday'})
RETURN tweet, COUNT(r)
ORDER BY COUNT(r) DESC

请记住,我们试图找到影响者,因此我们需要知道是谁发送了这些消息

MATCH (retweet:Message)-[r:FORWARD]->(tweet:Message)<-[:SENT]-(p:User)
RETURN p.id AS User, COUNT(r) AS `Messages Retweeted`
ORDER BY COUNT(r)
DESC LIMIT 5

由此可见,Bridget 的很多消息都被转发了,但 Mark 的消息转发次数更多。

如果您是 Twitter 或类似社交网络的用户,您会知道 Twitter 上有很多机器人只是简单地转发消息。我们希望从分析中删除这些机器人。

MATCH (p:User)-[s:SENT]->(tweet:Message)-[retweet:FORWARD]->(tweet1:Message), (p:User)-[s2:SENT]->(tweet2:Message)
WITH p, COUNT(DISTINCT tweet) AS forwards, COUNT(DISTINCT tweet2) AS messages
WHERE (forwards*1.00)/messages > 0.8
RETURN p.id AS `Potential Bot`, (forwards*1.00)/messages*100 AS `Percent Retweeted`
ORDER BY `Percent Retweeted` DESC

如您所见,Doug 只是转发消息,因此他可能是一个机器人。为了更好地了解影响力,我们需要将他以及分析中其他任何机器人删除

MATCH (p:User)-[s:SENT]->(tweet:Message)-[retweet:FORWARD]->(tweet1:Message), (p:User)-[s2:SENT]->(tweet2:Message)
WITH p, COUNT(DISTINCT tweet) AS forwards, COUNT(DISTINCT tweet2) AS messages
WHERE (forwards*1.00)/messages < 0.8
WITH p
MATCH (p)-[s:SENT]->(tweet:Message)-[rt:FORWARD]->(tweet1:Message)<-[:SENT]-(p1:User)
RETURN p1.id as User, COUNT(tweet) as `Retweeted Messages`
ORDER BY COUNT(tweet)
DESC LIMIT 15

请注意,我们现在寻找的是转发次数占其消息总次数的比例小于 80% 的用户。

如您所见,这显示了一幅略有不同的画面,因为 Mark 的消息只被机器人转发了。我想要从分析中删除转发者的原因是,人类转发者会进行一些筛选,只转发他们喜欢的东西。

现在,我们已经有了几个影响力指标,基于关注者数量和用户获得的转发次数。

我要调查的第三个指标是用户在 Twitter 上以及在多少人中开始对话或讨论的频率。

用例:对话作为影响力的衡量标准?

寻找对话是衡量影响力的一个很好的指标,因为它表明人们想要与该用户互动。

为了开始这项分析,让我们从获取对话列表开始,请注意,我已经限制了对话路径的长度,您可能需要考虑根据您的用例进行扩展。

MATCH p=(tweet:Message)-[:REPLY_TO*1..10]->(conversation:Message)
RETURN p

我们可以将其限制为单个对话

MATCH (tweet:Message {id:'20'})<-[:REPLY_TO*0..10]-(conversation:Message)
RETURN DISTINCT(conversation) AS Conversation
ORDER BY conversation.day_sent

请注意 DISTINCT(conversation),这将确保我们只在响应中获取每条消息的副本。

现在我们有了对话列表,让我们更深入地了解。

获取开始对话的消息列表,即有人回复的消息

MATCH (tweet:Message)-[r:REPLY_TO]->(conversation:Message)
WHERE NOT (conversation)-[:REPLY_TO]->()
RETURN DISTINCT conversation

并找出谁发送了开始对话的消息

MATCH (tweet:Message)-[:REPLY_TO]->(conversation:Message)<-[s:SENT]-(p:User)
WHERE NOT (conversation)-[:REPLY_TO]->()
RETURN DISTINCT conversation, p.id AS `Conversation Starter`

在此基础上,获取用户将与之互动并回复的用户列表,这表明存在比浅层“关注”关系更深层的联系。

MATCH conv=(b:User)-[:SENT]->(tweet:Message)-[:REPLY_TO]->(tweet1:Message)<-[:SENT]-(a:User)-[:SENT]->(tweet2:Message)-[:REPLY_TO]->(tweet)
RETURN a.id AS `Conversationalist 1`, b.id AS `Conversationalist 2`, COUNT(DISTINCT conv) AS Conversations
ORDER BY a.id ASC

我们还想知道对话的规模和参与的人数,一个涉及很多人的长对话比一个涉及几个人之间的短对话更能体现影响力。

MATCH (tweet:Message)-[r:REPLY_TO]->(conversation:Message)<-[s:SENT]-(p:User)
WHERE NOT (conversation)-[:REPLY_TO]->()
WITH DISTINCT conversation,p
MATCH conv=(participant:User)-[:SENT]->(tweet:Message)-[:REPLY_TO*0..10]->(conversation)
RETURN conversation, p, COUNT(DISTINCT participant) AS `Distinct Participants`

最后,再次修改查询以添加用户开始的对话数量。

MATCH (tweet:Message)-[r:REPLY_TO]->(conversation:Message)<-[s:SENT]-(p:User)
WHERE NOT (conversation)-[:REPLY_TO]->()
WITH DISTINCT conversation,p
MATCH conv=(participant:User)-[:SENT]->(tweet:Message)-[:REPLY_TO*0..10]->(conversation)
WITH conversation, p, COUNT(DISTINCT tweet) AS messageCount, COUNT(DISTINCT participant) AS participantCount
WHERE participantCount > 2
RETURN p.id, COUNT(p) AS `Conversations`, AVG(messageCount) AS `Average Length`, AVG(participantCount) AS `Average Participants`

如您所见,Alice 开始的对话更多,但 Mark 开始的对话参与度更高。您需要自己确定这些指标在您的网络中哪一个影响力更大。

结论

如您所见,Neo4j 是分析社交网络的强大工具,您可以使用以上的一些值来观察您的网络中的影响者。