R 데이터 프레임에서 하나의 특정 중복 레코드를 제외한 모든 레코드를 제거하려면 어떻게합니까? [닫은]


16

중복 ID가 포함 된 데이터 프레임이 있습니다. 중복 값이있는 레코드를 제거하고 최대 값을 가진 행만 유지하려고합니다.

따라서 다음과 같이 구조화됩니다 (다른 변수는 표시되지 않음).

id var_1
1 2
1 4
2 1
2 3
3 5
4 2

이것을 생성하고 싶습니다 :

id var_1
1 4
2 3
3 5
4 2

unique () 및 duplicated ()에 대해 알고 있지만 최대화 규칙을 통합하는 방법을 알 수 없습니다 ...


순전히 프로그래밍 관련 작업이므로 통계와 거의 관련이 없으므로 실제로
Enthusiast

답변:


24

한 가지 방법은 데이터를 역 정렬하고 duplicated모든 중복 항목을 삭제 하는 데 사용 하는 것입니다. 저에게이 방법은 개념적으로 적용하는 것보다 간단합니다. 나는 그것이 매우 빠르다고 생각합니다.

# Some data to start with:
z <- data.frame(id=c(1,1,2,2,3,4),var=c(2,4,1,3,5,2))
# id var
#  1   2
#  1   4
#  2   1
#  2   3
#  3   5
#  4   2

# Reverse sort
z <- z[order(z$id, z$var, decreasing=TRUE),]
# id var
#  4   2
#  3   5
#  2   3
#  2   1
#  1   4
#  1   2

# Keep only the first row for each duplicate of z$id; this row will have the
# largest value for z$var
z <- z[!duplicated(z$id),]

# Sort so it looks nice
z <- z[order(z$id, z$var),]
# id var
#  1   4
#  2   3
#  3   5
#  4   2

편집 : 나는 위의 역 정렬이 전혀 정렬 할 필요조차 없다는 것을 깨달았습니다 id. z[order(z$var, decreasing=TRUE),]대신 사용할 수 있으며 잘 작동합니다.

한 가지 더 생각 ... var열이 숫자 id이면 오름차순이지만 var내림차순 으로 정렬하는 간단한 방법 이 있습니다. 이렇게하면 마지막에 정렬 할 필요가 없습니다 (정렬되기를 원한다고 가정).

z <- data.frame(id=c(1,1,2,2,3,4),var=c(2,4,1,3,5,2))

# Sort: id ascending, var descending
z <- z[order(z$id, -z$var),]

# Remove duplicates
z <- z[!duplicated(z$id),]
# id var
#  1   4
#  2   3
#  3   5
#  4   2

1
이 접근 방식은 "분할 컴퓨팅 바인딩"보다 훨씬 빠릅니다. 또한 여러 요인으로 그룹화 할 수 있습니다. c. "주문 중복 된"접근 방식의 650,000 행 (8, 좁은, 열)은 55 초, 분할 계산 실행 시간은 1 시간 15 분이었습니다. 물론 집합 계산이 복제물을 선택하거나 필터링하는 것 이외의 경우, 후자의 접근법 또는 유사한 plyr 기반의 접근법이 필요하다.
mjv

7

실제로 동일한 ID를 가진 요소에서 최대 요소를 선택하려고합니다. 이를 위해 plyrddply 패키지에서 사용할 수 있습니다 .

> dt<-data.frame(id=c(1,1,2,2,3,4),var=c(2,4,1,3,4,2))
> ddply(dt,.(id),summarise,var_1=max(var))
   id var_1
1  1   4
2  2   3
3  3   4
4  4   2

unique그리고 duplicated귀하의 경우에 당신이뿐만 아니라 기록, 중복 ID를 가지고 중복 레코드를 제거하기위한 것입니다.

업데이트 : 추가 변수가있을 때의 코드는 다음과 같습니다.

> dt<-data.frame(id=c(1,1,2,2,3,4),var=c(2,4,1,3,4,2),bu=rnorm(6))
> ddply(dt,~id,function(d)d[which.max(d$var),])

다른 변수가 있다면 어떻게합니까?
Aniko

우리는 그러한 질문을하지 않습니다. 너무 적은 이익을 얻기 위해 서두르십시오.

6

base-R 솔루션은 다음과 split같이 관련됩니다 .

z<-data.frame(id=c(1,1,2,2,3,4),var=c(2,4,1,3,4,2))
do.call(rbind,lapply(split(z,z$id),function(chunk) chunk[which.max(chunk$var),]))

split데이터 프레임을 청크 목록으로 분할하여 최대 값으로 단일 행으로 절단을 수행 한 다음 do.call(rbind,...)단일 행 목록을 다시 데이터 프레임으로 줄입니다.


1
그리고 평소처럼 이것은 plyr 버전보다 약 2 배 빠릅니다.

1
@mbq, 예, 당연하지만 디버깅 비용을 포함하면 일반적인 데이터 세트의 경우 결과 속도는 같습니다 :) plyr은 하지 속도,하지만 선명도와 편의를 위해 최선을 다하고 있습니다.
mpiktas

그리고 ave를 사용하는 것은 어쨌든 두 배 빠릅니다 :)
Eduardo Leoni

2
@Eduardo avelapply+ 의 래퍼입니다 split. 코드를 확인하십시오 (-;

1
@Eduardo 그래, 그러나 그것은 모든 요소 내에서 벡터화 된 정렬 가능성으로 인해 작동합니다 order. 보다 일반적인 문제 split는 불가피합니다.

5

나는 사용하는 것을 선호합니다 ave

dt<-data.frame(id=c(1,1,2,2,3,4),var=c(2,4,3,3,4,2))
## use unique if you want to exclude duplicate maxima
unique(subset(dt, var==ave(var, id, FUN=max)))

+1, ave에 대해 몰랐습니다. 언제 R에 나타 났습니까?
mpiktas

1

기본으로 이것을 수행하는 또 다른 방법 :

dt<-data.frame(id=c(1,1,2,2,3,4),var=c(2,4,1,3,4,2))

data.frame(id=sort(unique(dt$var)),max=tapply(dt$var,dt$id,max))
  id max
1  1   4
2  2   3
3  3   4
4  4   2

그래도 mpiktas 'plyr 솔루션을 선호합니다.


1

예제에서와 같이 var 열이 이미 오름차순 인 경우 데이터 프레임을 정렬 할 필요가 없습니다. 우리는 단지 기능을 사용합니다duplicated 는 인수를 전달 를fromLast = TRUE 하기 때문에 마지막 요소를 유지하면서 뒷면에서 복제가 고려됩니다.

z <- data.frame(id=c(1,1,2,2,3,4),var=c(2,4,1,3,5,2))
z[!duplicated(z$id, fromLast = TRUE), ]

  id var
2  1   4
4  2   3
5  3   5
6  4   2

그렇지 않으면 먼저 데이터 프레임을 오름차순으로 정렬합니다.

z <- z[order(z$id, z$var), ]
z[!duplicated(z$id, fromLast = TRUE), ]

dplyr패키지 사용 :

library(dplyr)
z %>%
  group_by(id) %>%
  summarise(var = max(var))

Source: local data frame [4 x 2]    
  id var
1  1   4
2  2   3
3  3   5
4  4   2
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.