通过使用来自tibble中不同行的值来变量值

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了通过使用来自tibble中不同行的值来变量值相关的知识,希望对你有一定的参考价值。

我想计算一个节点到根dtr的距离。我只有一个向量,它包含每个节点rel的父节点id(在本例中id == 7是root):

library(tidyverse)

tmp <- tibble(
  id = 1:12,
  rel = c(2,7,4,2,4,5,7,7,10,8,7,7)
)

最后我正在寻找这个结果:

TMP $ DTR

[1] 2 1 3 2 3 4 0 1 3 2 1 1

到目前为止,我能够编写以下算法,直到我在尝试引用代码中的不同行时遇到困难。

该算法应该像这样工作(伪代码):

  1. 如果不是root,则增加dtrif(!equals(tid,trel)): dtr = dtr+1
  2. tid改为treltid = trel
  3. trel更改为rel值的id == trel
  4. 如果有任何!equals(tid,trel) GOTO 1.,否则END

首先,我添加了2个辅助列来存储临时信息:

tmp <- tmp %>%
  mutate(
    tid = id,
    trel = rel,
    dtr = 0
  )

算法的前两个步骤如下:

tmp <- tmp %>%
  mutate(
    dtr = if_else(
      !equals(tid,trel),
      dtr + 1,
      dtr
    ),
    tid = trel
  ) 

第三步我不确定....我尝试使用以下代码实现它,但这不起作用:

tmp <- tmp %>% 
  mutate(trel = rel[id == .$tid])

结果(当然)错了:

TMP $相对

[1] 7 7 7 7 7 7 7 7 7 7 7 7

但为什么不呢? (第一次运行时应该是正确的解决方案):

[1] 2 7 2 7 2 4 7 7 10 8 7 7

第四步是通过检查trel中是否有多个唯一值来完成:

while(length(unique(tmp$trel)) > 1){
  ...
}

因此,完整的算法应该看起来像这样:

get_dtr <- function(tib){
  tmp <- tib %>%
    mutate(
      tid = id,
      trel = rel,
      dtr = 0
    )

  while(length(unique(tmp$trel)) > 1){
    tmp <- tmp %>%
      mutate(
        dtr = if_else(
          !equals(tid,trel),
          dtr + 1,
          dtr
        ),
        tid = trel
      ) 

    ### Step 3
  }
  tmp
}

知道如何解决这个或更简单的解决方案吗?提前致谢!

答案

这基本上已经在tidygraph包中实现了。如果您打算使用tidyverse处理类似图形的数据,那么您应该首先查看。你可以做

library(tidygraph)
as_tbl_graph(tmp, directed=FALSE) %>% 
  activate(nodes) %>% 
  mutate(depth=bfs_dist(root=7)) %>% 
  as_tibble()
#     name depth
#    <chr> <int>
#  1     1     2
#  2     2     1
#  3     3     3
#  4     4     2
#  5     5     3
#  6     6     4
#  7     7     0
#  8     8     1
#  9     9     3
# 10    10     2
# 11    11     1
# 12    12     1
另一答案

如果您想自己编写函数,可以使用以下代码:

library(tidyverse)

tmp <- tibble(
  id = 1:12,
  rel = c(2,7,4,2,4,5,7,7,10,8,7,7)
)


calc_dtr <- function(id, tmp){
  # find root
  root <- tmp$id[tmp$id == tmp$rel]

  # is this the root node? 
  if(id == root){return(0)}

  # initialize counter
  dtr <- 1
  trel <- tmp$rel[tmp$id == id]

  while(trel != root){
    dtr <- dtr + 1
    trel <- tmp$rel[tmp$id == trel]
  }

  return(dtr)
}

tmp %>% 
  mutate(
    dtr = map_dbl(id, calc_dtr, tmp)
  )

这会产生以下输出:

# A tibble: 12 x 3
      id   rel   dtr
   <int> <dbl> <dbl>
 1     1     2     2
 2     2     7     1
 3     3     4     3
 4     4     2     2
 5     5     4     3
 6     6     5     4
 7     7     7     0
 8     8     7     1
 9     9    10     3
10    10     8     2
11    11     7     1
12    12     7     1

以上是关于通过使用来自tibble中不同行的值来变量值的主要内容,如果未能解决你的问题,请参考以下文章

我想通过匹配来自 mongo 数据库的值来选中复选框

通过java中不同类中的静态方法设置和获取静态变量值

Vue.js:通过循环遍历数组值来绑定文本字段的值

通过连接来自不同列的逗号分隔值来创建字符串

如何比较来自同一列和不同行但同一表的值?

如何比较来自不同列和不同行但同一张表的值?