簡體   English   中英

Function 在數據框中查找 ID 的子 ID

[英]Function to find sub ID's of an ID in a data frame

我有一個包含兩列的數據框,一個 ID 列和一個具有與相應 ID 相關的子 ID 的列。 子 ID 可以再次具有子 ID(在這種情況下,以前的子 ID 現在是一個 ID)。

library(tibble)

df <- tibble(id = c(1, 1, 2, 2, 3, 7), sub_id = c(2, 3, 4, 5, 6, 8))

df

# A tibble: 6 x 2
     id sub_id
  <dbl>  <dbl>
1     1      2
2     1      3
3     2      4
4     2      5
5     3      6
6     7      8

我想寫一個 function 來查找與 ID 相關的所有子 ID。 它應該返回一個包含所有子 ID 的向量。

find_all_sub_ids <- function (data, id) {
data %>% ...
}

find_all_sub_ids(df, id = 1)

[1] 2 3 4 5 6

find_all_sub_ids(df, id = 2)

[1] 4 5

find_all_sub_ids(df, id = 9)

[1] NULL

這與迄今為止我在 R 中所做的一切都非常不同,我很難為這個問題寫一個好的標題。 因此,如果使用正確的措辭,我可能已經通過谷歌搜索找到了答案。

我解決這個問題的第一個直覺是 while 循環。 由於我也不知道可能有多少子級別,function 應該繼續直到找到所有子級別。 我從來沒有使用過while循環,也不知道如何在這里實現它們。

也許有人知道解決這個問題的好方法。 謝謝!

編輯:忘記將 tibble 分配給 df 並在 function 調用中使用此參數。

使用igraph

library(igraph)
g <- graph_from_data_frame(d, directed = TRUE)

find_all_subs <- function(g,id){
  #find child nodes, first one being origin
  r <- igraph::subcomponent(g,match(id, V(g)$name),"out")$name
  #remove origin
  as.numeric(r[-1])
}
find_all_subs(g,1)
[1] 2 3 4 5 6

find_all_subs(g,2)
[1] 5 6

我認為將其表述為圖形問題最容易。
您的 data.frame 描述了一個有向圖(從 id 到 sub_id 的頂點),並且您對從某個頂點可到達哪些節點感興趣。

使用tidygraph ,可以這樣實現:

library(tidyverse)
library(tidygraph)

df <- tibble(id = c(1, 1, 2, 2, 3, 7), sub_id = c(2, 3, 4, 5, 6, 8))

find_all_sub_ids <- function (id) {
  if (!(id %in% df$id)) {
    return(NULL)
  }

  
  grph <- df %>% 
    as_tbl_graph(directed = TRUE)
  
  id <- which(grph %>% pull(name) == as.character(id))
  
  grph %>% 
    activate(nodes) %>% 
    mutate(reachable = !is.na(bfs_dist(id))) %>% 
    as_tibble() %>% 
    filter(reachable) %>% 
    pull(name) %>% 
    as.numeric()
}

我們查看哪些節點是可訪問的(它們與您的給定節點有非 NA 距離),我們使用bfs_dist (請參閱此處進行解釋)。
這給

> find_all_sub_ids(1)
[1] 1 2 3 4 5 6

> find_all_sub_ids(2)
[1] 2 4 5

> find_all_sub_ids(9)
NULL

這種方法的優點是它可以搜索很多層次,而無需顯式地編寫循環。

編輯我的代碼中有一個錯誤, tidygraph::bfs_dist使用的 id 與我預期的不同。 現在修好了。
在新示例中:

> find_all_sub_ids(10)
[1]  10 200 300

我使用 dataframe 做到了。 以下作品。

x= c(1,1,2,2,3,7)
y = c(2, 3, 4, 5, 6, 8)
df <- data.frame(cbind(x,y))
colnames(df) =c('id', 'sub_id')


find_all_sub_ids <- function (df, id_requested) {
  si <- df[df$id==id_requested,]$sub_id
  return(si)
}
find_all_sub_ids(df,id=2)
[1] 4 5

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM