【问题标题】:dataframe query in R nodes graphR节点图中的数据框查询
【发布时间】:2018-03-27 02:52:55
【问题描述】:

我有数据框

df<-data.frame(source=c("a","a","a",'z1','b'),target=c("b","c","d",'a','e'),wsource=c('w1','w2','w1','w2','w1'),wtarget=c('w1','w1','w1','w1','w2'))

source target wsource wtarget
 a      b       w1       w1
 a      c       w1       w1
 a      d       w1       w1
z1      a       w2       w1
 b      e       w1       w2

表示一个图(sourcetarget 是节点 ID,wsourcewtarget 是标签)。我想为每个不同的节点获取它与 wtarget 关联的次数(如果该节点位于源列中)加上它与 wsource 关联的次数(如果该节点是目标列)。

我要找的数据框是:

node w1 w2
  a  3  1
  b  1  1
  c  1  0
  d  1  0
  e  1  0
 z1  1  0

请注意,例如,节点 a 在列 w1 中的 3 来自它作为源出现的三次(查看其对应的 wtarget),并从它所在的第四行获取其在列 w2 中的 1显示为目标(查看其对应的 wsource)。

我尝试先对列进行排序,但在我的应用程序中,节点 ID 是长整数。即使您对它们进行排序,也不能保证一个节点只会出现在一列(源或目标)中。

我想知道处理这个查询的方法。

【问题讨论】:

  • 我承认我迷路了。我不明白你在制表什么。
  • 我知道,这很难解释。对于每个不同的节点,我需要计算在wsourcewtarget 中分配的w1w2 的数量。但请注意,一个节点可能同时出现在 source 和 target 列中。

标签: r dataframe join


【解决方案1】:

取消列表和表格:

source--targetwtarget--wsource 对齐,以便将所有节点放在一列中,并将所有标签放在另一列中,并使用table 生成结果:

table(
  unlist(df[c("source","target")]),
  unlist(df[c("wtarget","wsource")])
)

#       w1 w2
#    a   3  1
#    b   1  1
#    c   0  1
#    d   1  0
#    e   1  0
#    z1  1  0

【讨论】:

    【解决方案2】:

    你可以通过

    library(dplyr)
    library(tidyr)
    df <- data.frame(source=c("a","a","a",'z1','b'),target=c("b","c","d",'a','e'),wsource=c(1,2,1,2,1),wtarget=c(1,1,1,1,2), stringsAsFactors = FALSE)
    df <- rbind(as.matrix(df[, c(1, 4)]), as.matrix(df[, c(2, 3)]))
    df <- df %>% data.frame %>% group_by(source, wtarget) %>% summarise(n = n()) %>%
      spread(wtarget, n) %>% mutate(`1` = ifelse(is.na(`1`), 0, `1`), `2` = ifelse(is.na(`2`), 0, `2`))
    apply(df, 2, function(x) ifelse(is.na(x), 0, x))
    
    # A tibble: 6 x 3
    # Groups: source [6]
      source   `1`   `2`
      <fctr> <dbl> <dbl>
    1 a       3.00  1.00
    2 b       1.00  1.00
    3 c       0     1.00
    4 d       1.00  0   
    5 e       1.00  0   
    6 z1      1.00  0  
    

    我希望这会有所帮助!

    【讨论】:

    • 如果我们不仅有两个 wis 而是几十个,您的代码将如何变化?
    • 我做了一个更小的编辑来更健壮。代码应该可以处理很多wis。
    【解决方案3】:

    获取完整的节点列表:

    sources<-unique(df$source)
    targets<-unique(df$target)
    st<-unique(c(sources,targets))
    

    for 循环设置变量:

    node<-NULL
    w1<-NULL
    w2<-NULL
    

    创建列:

    for(i in 1:length(st)) {
      node[i]<-st[i]
      w1[i]<-sum(df$wtarget[df$source==st[i]]==1, df$wsource[df$target==st[i]]==1)
      w2[i]<-sum(df$wtarget[df$source==st[i]]==2, df$wsource[df$target==st[i]]==2)
    }
    

    使用 cbind 将所有内容组合在一起:

    cbind(node,w1,w2)
    

    结果:

          node w1  w2 
     [1,] "a"  "3" "1"
     [2,] "z1" "1" "0"
     [3,] "b"  "1" "1"
     [4,] "c"  "0" "1"
     [5,] "d"  "1" "0"
     [6,] "e"  "1" "0"
    

    如果你想要这个命令,你可以添加以下行:

    nodelist<-cbind(node,w1,w2)
    nodelist<-nodelist[order(nodelist[,1]),]
    
         node w1  w2 
    [1,] "a"  "3" "1"
    [2,] "b"  "1" "1"
    [3,] "c"  "0" "1"
    [4,] "d"  "1" "0"
    [5,] "e"  "1" "0"
    [6,] "z1" "1" "0"
    

    更新:这是多个 w 的通用版本:

    sources<-unique(df$source)
    targets<-unique(df$target)
    st<-unique(c(sources,targets))
    node<-NULL
    nodes<-NULL
    w<-NULL
    for(t in 1:max(c(df$wsource,df$wtarget))) {
      for(i in 1:length(st)) {
        node[i]<-st[i]
        w[i]<-sum(df$wtarget[df$source==st[i]]==t,     df$wsource[df$target==st[i]]==t)
      }
      nodes<-cbind(nodes,w)
    }
    nodelist<-data.frame(cbind(node,nodes))
    nodelist<-nodelist[order(nodelist[,1]),]
    

    您需要做更多的工作来修复列名,但这应该不会太难。

    【讨论】:

    • 好一个!如果我们有几十个wi,会发生什么? (忘了在问题中提到这一点)我想避免 for 循环。
    • 添加了通用版
    猜你喜欢
    • 1970-01-01
    • 2012-01-03
    • 2019-04-29
    • 1970-01-01
    • 2015-03-22
    • 1970-01-01
    • 2019-05-26
    • 2016-07-06
    • 1970-01-01
    相关资源
    最近更新 更多