루프를 사용하지 않고 행을 그룹화하고 각 그룹에 인덱스를 할당하는 방법을 찾으려고합니다. 어려운 점은 그룹화 변수 num 에 고유 식별자가 없다는 것입니다. num 은 숫자 로 구성된 벡터입니다 (문자로 정의 됨). 적어도 벡터의 숫자와 일치하는 모든 행을 그룹화하고 싶습니다. 벡터는 길이가 다르며 최대 20 개의 숫자를 포함합니다. 예를 들어 보겠습니다.
다음과 같은 데이터 프레임이 있습니다.
df <- data.frame(id = c(1:5), num = c('111;222', '333;111;444', '000;88888;1', '9999;111', '1'))
나는 구분자로 num 을 나눈다 . 모든 행이 벡터가되도록 :
library(dplyr)
df <- df %>%
mutate(num = str_split(num, ';'))
벡터에서 하나 이상의 숫자가 동일한 인덱스와 일치하는 모든 행을 인덱싱하고 싶습니다. 결과는 다음과 같습니다.
id num group_index
1 c('111','222') 1
2 c('333','111','444') 1
3 c('000','88888','1') 2
4 c('9999','444') 1
5 '1' 2
이 예에서는 또 다른 난이도를 보여줍니다. 1 행이 그룹 1의 일부이고 num에 '444'가 포함되어 있지 않더라도 그룹 1은 '111'과 '444'로 식별됩니다 .
경우 납입은 단지 문자열이고, 나는 다음을 수행 할 것
df <- group_by(num) %>%
mutate(group_index = group_indices(.,num))
이제 그룹을 식별하는 것부터 시작해야한다고 생각했습니다. 작동하지 않는 첫 번째 방법은 다음과 같습니다.
df <- df %>%
group_by_if(num, any(num, str_c(num, collapse = '|')) == T)
루프를 작성하는 것으로 시작할 수 있다는 것을 알고 있습니다. 그러나 R은 루프에서 매우 효율적이지 않으므로 루프가없는 솔루션을 선호합니다. 어떤 힌트라도 도움이 될 것입니다!
좋아,이 대답은 아마도 짧아 질 수 있지만 (아마 많이 ) igraph
그룹 수를 시각적으로 검사하기 위해 모든 것을 멋지고 눈에 띄게 유지 한다고 생각합니다 .
library( data.table )
library( igraph )
#make df a data.table
setDT(df)
#split num-column to v1, v2, ... ,vn
df[, paste0("v", 1:length( tstrsplit(df$num, ";"))) := tstrsplit( num, ";")]
# id num v1 v2 v3
# 1: 1 111;222 111 222 <NA>
# 2: 2 333;111;444 333 111 444
# 3: 3 000;88888;1 000 88888 1
# 4: 4 9999;111 9999 111 <NA>
# 5: 5 1 1 <NA> <NA>
#now melt to long format
df.melt <- melt(df, id.vars = "id", measure.vars = patterns("^v[0-9]"), value.name = "from" )
#create links
df.melt[, to := shift( from, type = "lead"), by = .(id)][]
#drop inomplete rows
df.melt <- df.melt[ complete.cases(df.melt), ]
# id variable from to
# 1: 1 v1 111 222
# 2: 2 v1 333 111
# 3: 3 v1 000 88888
# 4: 4 v1 9999 111
# 5: 2 v2 111 444
# 6: 3 v2 88888 1
g = graph_from_data_frame( df.melt[ , .(from, to)])
# plot(g)
함께 작업 할 두 개의 개별 그룹이있는 것 같습니다. 어떤 노드 (번호)가 어떤 그룹에 속하는지 알아 내고이 정보를 원본 df에 사용합니다.
dt.lookup <- as.data.table( components(g)$membership, keep.rownames = TRUE )
# V1 V2
# 1: 111 1
# 2: 333 1
# 3: 000 2
# 4: 9999 1
# 5: 88888 2
# 6: 222 1
# 7: 444 1
# 8: 1 2
#go back to the molten data of the original df
df.melt <- melt(df, id.vars = "id", measure.vars = patterns("^v[0-9]"))
df.melt <- df.melt[ complete.cases(df.melt), ]
#perform update join to get the groupnumber
df.melt[ dt.lookup, group := i.V2, on = .(value = V1) ]
# id variable value group
# 1: 1 v1 111 1
# 2: 2 v1 333 1
# 3: 3 v1 000 2
# 4: 4 v1 9999 1
# 5: 5 v1 1 2
# 6: 1 v2 222 1
# 7: 2 v2 111 1
# 8: 3 v2 88888 2
# 9: 4 v2 111 1
# 10: 2 v3 444 1
# 11: 3 v3 1 2
#summarise to go back to oroiginal df form
df.melt[, .(num = paste0( value, collapse = ";"),
group = paste0( unique(group), collapse = ",")),
by = .(id) ][]
최종 출력
# id num group
# 1: 1 111;222 1
# 2: 2 333;111;444 1
# 3: 3 000;88888;1 2
# 4: 4 9999;111 1
# 5: 5 1 2
이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.
침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제
몇 마디 만하겠습니다