【问题标题】:creating network data from event level data从事件级数据创建网络数据
【发布时间】:2020-01-19 09:44:33
【问题描述】:

作为网络分析的新手,我正在努力将要绘制的事件级数据集转换为正确的形状。我很感谢任何提示/线索/等。到目前为止,我所做的大致遵循 this 介绍。

相关数据集包含政党 Jobbik 组织的活动。每个由唯一 ID (id) 定义的事件都有关联的组织发起人 (org_names) 及其类型 (org)。 org_1org_2org_names1org_names2 之间没有层次结构。

最初数据集采用宽格式。虽然我不确定这是否是我应该做的,但我要做的第一步是将数据转换为长格式并清理一些字符串。这是读取数据并将其转换为长格式的代码:

jobbik <- read.csv("http://eborbath.github.io/stackoverflow/jobbik.csv")


library(tidyverse)
library(stringr)
library(igraph)

# long format

jobbik <- reshape(as.data.frame(jobbik), dir='long',
                  varying=list(c(3:13), c(14:24)),
                  v.names=c('org_names', 'org'), times = c(as.character(seq(1:11))))
jobbik$org <- str_trim(jobbik$org, side="both")
jobbik$org_names <- str_trim(jobbik$org_names, side="both")
jobbik <- jobbik %>%
  filter(!(org=="no other organizer" & org_names=="")) %>%
  filter(!(org=="JOBBIK" & org_names %in% c("Jobbik",
                                            "Jobbik Magyarországért Mozgalom",
                                            "",
                                            "JObbik",
                                            "jobbik",
                                            "aktivisté Jobbiku",
                                            "a Jobbik"))) %>% 
  mutate(org_names=ifelse(org_names=="", org, org_names)) %>%
  distinct(.)

下一步我要创建网络数据集。为此,我计算了每个独特组织参与 Jobbik 活动的次数。将 Jobbik 添加为每条边的一侧并使用 igraph 绘制数据:

network <- jobbik %>%
  select(id, org_names) %>% 
  group_by(org_names) %>%
  summarise(weight = n()) %>% 
  ungroup() %>% 
  mutate(from=1,
         org_names=as.factor(org_names)) %>% 
  mutate(org_id=as.numeric(factor(org_names)))

edges <- network %>% select(from, org_id, weight)
nodes <- network %>% select(org_id, org_names) %>% 
  mutate(org_names=as.character(org_names))


routes_igraph <- graph_from_data_frame(d = edges, vertices = nodes, directed = FALSE)

plot(routes_igraph, layout = layout_with_graphopt)

虽然它运行并创建了网络,但它只让我了解每个独特组织与 Jobbik 之间的关系,而不是这些不涉及 Jobbik 的组织之间的关系。我意识到错误出在我所做的数据转换中,我应该使用事件级别的信息来计算每个组织对参与组织某事的次数,然后绘制该数据。不幸的是,虽然我不知道如何到达那里。我很感激任何帮助。

【问题讨论】:

    标签: r igraph network-analysis data-transform


    【解决方案1】:

    我并不是网络分析方面的专家,尤其是igraph。但我认为这样的事情可能会有所帮助。

    我更改了您分析的预处理部分,因为我在某种程度上发现了一些并发症:

    1. 匈牙利语的编码:找到正确的编码需要时间(参见read_csv 调用中的locale = 'cp1250
    2. 收集后我将org_name* 更改为orgorg* 更改为type
    3. 我使用chopspread 更容易 -> unnest;
    4. 我尝试缩短 filter 的通话时间,但没有取得很大成功;
    5. 我使用stringr::str_to_title()来统一org var,因为有相同的名称,只是名称的第n个单词是否大写;
    6. 我使用coalesce 用来自type var 的值填充org var 的NAs。

      library(tidyverse)
      library(magrittr)
      library(igraph)
      
      jobbik <- read_csv(
        "http://eborbath.github.io/stackoverflow/jobbik.csv", 
        trim_ws = T, 
        locale = locale(encoding = 'cp1250')
        )
      
      jobbik %<>%
        gather('key', 'val', -c('id', 'date')) %>%
        mutate(
          key = case_when(
            grepl('^org_names\\d+$', key) ~ 'org',
            grepl('^org\\d+$',       key) ~ 'type',
            TRUE                         ~ key
          )
        ) %>%
        chop(val) %>%
        spread(key, val) %>%
        unnest(c(org, type)) %>%
        filter(
          !(is.na(org) & (type == 'no other organizer')) &
          !((is.na(org) | grepl('.*jobbik.*', org, T  )) & (type == 'JOBBIK'))
        ) %>%
        mutate(org = str_to_title(coalesce(org, type)))
      

    为了形成图边的数据框,我按事件的id 分组,过滤掉仅由一个组织支持的所有事件(因此与其他组织没有联系),最后创建对在id 内具有combn 功能的组织之间。结果是字符向量Org A-Org B,在取消嵌套之后,我使用- 作为拆分将其分成fromto(如果组织名称有-,这可能很危险)中的符号)。如果有的话,我也会过滤掉所有的自循环。最后一个操作是count,用于计算每一对出现在 Jobbik 会议列表中的频率。我将它分配给width,因为在绘图时,igraph::plot 将使用它作为边缘的宽度。

    ed <- jobbik %>%
      group_by(id) %>%
      filter(n() > 1) %>%
      summarise(edge = list(combn(org, 2, paste, collapse = '-'))) %>%
      unnest(edge) %>%
      separate(edge, into = c('from', 'to'), sep = '-') %>%
      filter(from != to) %>%
      count(from, to, name = width)
    

    对顶点执行类似的分析。我在这里添加了顶点的额外信息,即事件iddate、组织type,您可以进一步使用它们,color - 映射给定组织的次数。支持 Jobbik 和一些额外的图形参数用于后一个图。

    nd <- jobbik %>%
      filter(org %in% c(ed$from, ed$to)) %>%
      group_by(name = org) %>%
      summarise(
        id   = sprintf('Event ids: %s', paste(id, collapse = ', ')),
        date = sprintf('Event dates: %s', paste(date, collapse = ', ')),
        type = sprintf('Org. type: %s',   paste(type, collapse = '; ')),
        color = n() 
      ) %>%
      ungroup() %>%
      mutate(
        color = heat.colors(10)[cut(color, 10)],
        frame.color = NA,
        label.dist = 1,
        label.cex = .5,
        label.color = 'gray10'
      )
    

    有了这些数据,我们可以制作无向图,使用graph_from_data_frame()函数:

    g <- graph_from_data_frame(ed, F, nd)
    vertex_attr(g, 'size') <- degree(g, mode = 'all')
    

    在上面的第二行中,我添加了顶点属性size 以将顶点的度数映射到顶点的大小。

    最后要绘制社区,我可以这样做:

    plot(
      g,
      edge.curved  = .2,
      layout = layout_with_kk,
      asp = 1,
      main = 'Jobbik interaction network',
      )
    

    【讨论】:

    • 哦,我忘了告诉g &lt;- delete.vertices(simplify(g), degree(g)==0),我还删除了度数== 0的顶点,所以最终图表上没有显示一直支持Jobbik的组织。
    • @eborbath 我很高兴知道我可以提供帮助。我看过你文章的标题——听起来很有趣。只是,请检查每一步是否有任何隐藏的错误,我认为一般的想法是正确的,但正如我所说 - 我不是专家,不幸的是我不是一个防错的:)
    猜你喜欢
    • 2013-06-23
    • 1970-01-01
    • 1970-01-01
    • 2020-07-14
    • 2012-11-17
    • 1970-01-01
    • 2023-03-18
    • 2019-04-02
    • 1970-01-01
    相关资源
    最近更新 更多