"작은 첨자가있는 요소"를 포함하여 모든 중복 행 찾기


111

R 's duplicated는 벡터 또는 데이터 프레임의 각 요소가 더 작은 첨자를 가진 요소의 복제본인지 여부를 나타내는 벡터를 반환합니다. 따라서 5 행 데이터 프레임의 3, 4, 5 행이 동일 duplicated하면 벡터를 얻을 수 있습니다.

FALSE, FALSE, FALSE, TRUE, TRUE

하지만이 경우에는 실제로

FALSE, FALSE, TRUE, TRUE, TRUE

즉, 행이 더 큰 첨자를 가진 행에 의해 중복되는지 여부를 알고 싶습니다 .

답변:


128

duplicatedfromLast인수를. 의 "예제"섹션은 ?duplicated사용 방법을 보여줍니다. 그냥 전화 duplicated한 번, 두 번 fromLast=FALSE에 한 번 fromLast=TRUE와 중 하나 인 행을 TRUE.


일부 후기 편집 : 재현 가능한 예제를 제공하지 않았으므로 @jbaums가 친절하게 기고 한 그림이 있습니다.

vec <- c("a", "b", "c","c","c") 
vec[duplicated(vec) | duplicated(vec, fromLast=TRUE)]
## [1] "c" "c" "c"

편집 : 데이터 프레임의 경우 예 :

df <- data.frame(rbind(c("a","a"),c("b","b"),c("c","c"),c("c","c")))
df[duplicated(df) | duplicated(df, fromLast=TRUE), ]
##   X1 X2
## 3  c  c
## 4  c  c

3
잠시만 요, 방금 테스트를했는데 제가 틀렸다는 것을 발견했습니다. x <- c(1:9, 7:10, 5:22); y <- c(letters, letters[1:5]); test <- data.frame(x, y); test[duplicated(test$x) | duplicated(test$x, fromLast=TRUE), ]7, 8, 9의 3 개 사본을 모두 반환했습니다 . 왜 작동합니까?
JoeM05 2017

1
중간 부분은 끝에서 시작하든 앞에서 시작하든 상관없이 캡처되기 때문입니다. 예를 들어 duplicated(c(1,1,1))vs duplicated(c(1,1,1,), fromLast = TRUE)gives c(FALSE,TRUE,TRUE)c(TRUE,TRUE,FALSE). TRUE두 경우 모두 중간 값입니다 . |두 벡터를 모두 취 하면 c(TRUE,TRUE,TRUE).
브랜든

34

duplicated값 집합을 조합하고을 적용한 unique다음을 사용하여 테스트해야 %in%합니다. 항상 그렇듯이 샘플 문제로 인해이 프로세스가 활성화됩니다.

> vec <- c("a", "b", "c","c","c")
> vec[ duplicated(vec)]
[1] "c" "c"
> unique(vec[ duplicated(vec)])
[1] "c"
>  vec %in% unique(vec[ duplicated(vec)]) 
[1] FALSE FALSE  TRUE  TRUE  TRUE

동의하다. 처리 속도를 늦출 수도 있지만 그다지 느리지는 않을 것입니다.
IRTFM

사실입니다. OP는 데이터 프레임에서 "중복 된"행을 테스트하기위한 데이터 예제를 제공하지 않았습니다. 내가 사용하는 내 제안을 생각 duplicated, unique그리고 %in%하나는 처음에 인 경우에 쉽게 dataframe에 일반화 될 수있는 paste특이한 분리 문자로 각 행. (허용 대답은 더 좋다.)
IRTFM

3

저도 같은 질문을 했는데 제가 틀리지 않았다면 이것도 답입니다.

vec[col %in% vec[duplicated(vec$col),]$col]

어느 쪽이 더 빠른지 Dunno, 현재 사용중인 데이터 세트는 상당한 시간 차이를 생성하는 테스트를 수행 할만큼 충분히 크지 않습니다.


1
이 답변은 vec원자 벡터와 데이터 프레임으로 모두 사용되는 것 같습니다 . 실제 datframe을 사용하면 실패 할 것이라고 생각합니다.
IRTFM

3

데이터 프레임의 중복 행은 다음 dplyr을 수행 하여 얻을 수 있습니다.

df = bind_rows(iris, head(iris, 20)) # build some test data
df %>% group_by_all() %>% filter(n()>1) %>% ungroup()

특정 열을 제외 group_by_at(vars(-var1, -var2))하는 대신 데이터를 그룹화하는 데 사용할 수 있습니다.

데이터뿐 아니라 행 인덱스가 실제로 필요한 경우 다음과 같이 먼저 추가 할 수 있습니다.

df %>% add_rownames %>% group_by_at(vars(-rowname)) %>% filter(n()>1) %>% pull(rowname)

1
의 좋은 사용 n(). 결과 데이터 프레임을 그룹 해제하는 것을 잊지 마십시오.
qwr

@qwr 나는 결과 그룹을 해제 할 수있는 답변을 조정 한
홀거 브랜

2

다음은 @Joshua Ulrich의 솔루션입니다. 이 형식을 사용하면 duplicated ()를 사용하는 것과 동일한 방식으로이 코드를 사용할 수 있습니다.

allDuplicated <- function(vec){
  front <- duplicated(vec)
  back <- duplicated(vec, fromLast = TRUE)
  all_dup <- front + back > 0
  return(all_dup)
}

동일한 예를 사용하여 :

vec <- c("a", "b", "c","c","c") 
allDuplicated(vec) 
[1] FALSE FALSE  TRUE  TRUE  TRUE

0

특정 열에 대해 중복되는 행에 관심이있는 경우 plyr 접근 방식을 사용할 수 있습니다 .

ddply(df, .(col1, col2), function(df) if(nrow(df) > 1) df else c())

dplyr 로 카운트 변수 추가 :

df %>% add_count(col1, col2) %>% filter(n > 1)  # data frame
df %>% add_count(col1, col2) %>% select(n) > 1  # logical vector

중복 행의 경우 (모든 열 고려) :

df %>% group_by_all %>% add_tally %>% ungroup %>% filter(n > 1)
df %>% group_by_all %>% add_tally %>% ungroup %>% select(n) > 1

이러한 접근 방식의 이점은 컷오프로 중복 항목 수를 지정할 수 있다는 것입니다.


0

비슷한 문제가 있었지만 특정 열의 값으로 중복 된 행을 식별해야했습니다. 다음 dplyr 솔루션을 생각해 냈습니다 .

df <- df %>% 
  group_by(Column1, Column2, Column3) %>% 
  mutate(Duplicated = case_when(length(Column1)>1 ~ "Yes",
                            TRUE ~ "No")) %>%
  ungroup()

코드는 특정 열을 기준으로 행을 그룹화합니다. 그룹의 길이가 1보다 크면 코드는 그룹의 모든 행을 중복 된 것으로 표시합니다. 완료되면 Duplicated필터링 등을 위해 열을 사용할 수 있습니다 .

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.