![](/img/trans.png)
[英]R merge two data.frame by id and sub-id while changing column names?
[英]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.