원래 행 순서를 유지하면서 두 데이터 프레임 병합
그중 하나의 원래 행 순서를 지키면서 두 개의 데이터 프레임을 병합하려고 합니다 (df.2
아래의 예에서).
다음은 몇 가지 샘플 데이터입니다(모든 값:class
열은 두 데이터 프레임 모두에서 정의됩니다.)
df.1 <- data.frame(class = c(1, 2, 3), prob = c(0.5, 0.7, 0.3))
df.2 <- data.frame(object = c('A', 'B', 'D', 'F', 'C'), class = c(2, 1, 2, 3, 1))
다음을 수행할 경우:
merge(df.2, df.1)
출력:
class object prob
1 1 B 0.5
2 1 C 0.5
3 2 A 0.7
4 2 D 0.7
5 3 F 0.3
추가하면sort = FALSE
:
merge(df.2, df.1, sort = F)
결과는 다음과 같습니다.
class object prob
1 2 A 0.7
2 2 D 0.7
3 1 B 0.5
4 1 C 0.5
5 3 F 0.3
하지만 제가 원하는 것은:
class object prob
1 2 A 0.7
2 1 B 0.5
3 2 D 0.7
4 3 F 0.3
5 1 C 0.5
df.2의 행 번호를 나타내는 변수만 생성하면 됩니다.그런 다음 데이터를 병합한 후 이 변수에 따라 새 데이터 집합을 정렬합니다.다음은 예입니다.
df.1<-data.frame(class=c(1,2,3), prob=c(0.5,0.7,0.3))
df.2<-data.frame(object=c('A','B','D','F','C'), class=c(2,1,2,3,1))
df.2$id <- 1:nrow(df.2)
out <- merge(df.2,df.1, by = "class")
out[order(out$id), ]
plyr 패키지에서 join 기능을 확인해보세요.이것은 병합과 같지만 데이터 세트 중 하나의 행 순서를 유지할 수 있게 해줍니다.전반적으로 합병보다 유연성이 뛰어납니다.
우리는 당신의 예 데이터를 사용하여,join
다음과 같이:
> join(df.2,df.1)
Joining by: class
object class prob
1 A 2 0.7
2 B 1 0.5
3 D 2 0.7
4 F 3 0.3
5 C 1 0.5
다음은 행 순서를 유지하기 위한 병합 함수에 대한 수정 사항을 설명하는 몇 가지 링크입니다.
http://www.r-statistics.com/2012/01/merging-two-data-frame-objects-while-preserving-the-rows-order/
당신은 또한 확인할 수 있습니다.inner_join
해들리의 기능dplyr
패키지(다음 버전)plyr
첫 의 행 첫 번째 데이터 집합의 행 순서를 유지합니다.원하는 솔루션과 약간 다른 점은 첫 번째 데이터 집합의 원래 열 순서도 유지된다는 점입니다.따라서 합병 시 사용했던 컬럼을 반드시 첫 번째 위치에 배치하지는 않습니다.
위의 예시를 사용하면,inner_join
결과는 다음과 같습니다.
inner_join(df.2,df.1)
Joining by: "class"
object class prob
1 A 2 0.7
2 B 1 0.5
3 D 2 0.7
4 F 3 0.3
5 C 1 0.5
data.table v1.9.5+에서 다음 작업을 수행할 수 있습니다.
require(data.table) # v1.9.5+
setDT(df.1)[df.2, on="class"]
는 열에 조인을 수행합니다.class
일치하는 행을 찾음df.1
의 각 df.2
해당하는 열을 추출합니다.
완전성을 위해 조인에서 업데이트하면 원래 행 순서도 유지됩니다.추가할 열이 몇 개뿐인 경우 이는 아룬의 대답에 대한 대안이 될 수 있습니다.
library(data.table)
setDT(df.2)[df.1, on = "class", prob := i.prob][]
object class prob 1: A 2 0.7 2: B 1 0.5 3: D 2 0.7 4: F 3 0.3 5: C 1 0.5
여기서,df.2
에 바로 가입되어 있습니다.df.1
그리고 새 칼럼을 얻습니다.prob
일치하는 행에서 복사되는df.1
.
승인된 답변은 사용할 때 질서를 유지하는 수동 방법을 제안합니다.merge
, 대부분의 경우 작동하지만 불필요한 수작업이 필요합니다.이 솔루션은 정렬하지 않고 ddply()를 적용하는 방법(How to ddply?)을 통해 제공되며, 이는 질서를 유지하는 문제를 다루지만 분할 적용-결합 맥락에서 다루고 있습니다.
이것은 얼마 전에 (@kohske less) plyrer 메일링 리스트에 올라왔고, 이것은 Peter Milstrup이 한정된 경우에 제공하는 솔루션입니다.
#Peter's version used a function gensym to
# create the col name, but I couldn't track down
# what package it was in.
keeping.order <- function(data, fn, ...) {
col <- ".sortColumn"
data[,col] <- 1:nrow(data)
out <- fn(data, ...)
if (!col %in% colnames(out)) stop("Ordering column not preserved by function")
out <- out[order(out[,col]),]
out[,col] <- NULL
out
}
이제 이 제네릭을 사용할 수 있습니다.keeping.order
a의 원래 행 순서를 유지하는 함수merge
출:
df.1<-data.frame(class=c(1,2,3), prob=c(0.5,0.7,0.3))
df.2<-data.frame(object=c('A','B','D','F','C'), class=c(2,1,2,3,1))
keeping.order(df.2, merge, y=df.1, by = "class")
요청에 따라 다음과 같은 결과가 발생합니다.
> keeping.order(df.2, merge, y=df.1, by = "class")
class object id prob
3 2 A 1 0.7
1 1 B 2 0.5
4 2 D 3 0.7
5 3 F 4 0.3
2 1 C 5 0.5
그렇게keeping.order
승인된 답변에서 접근 방식을 효과적으로 자동화합니다.
@PAC 덕분에 다음과 같은 것을 생각해 냈습니다.
merge_sameord = function(x, y, ...) {
UseMethod('merge_sameord')
}
merge_sameord.data.frame = function(x, y, ...) {
rstr = paste(sample(c(0:9, letters, LETTERS), 12, replace=TRUE), collapse='')
x[, rstr] = 1:nrow(x)
res = merge(x, y, all.x=TRUE, sort=FALSE, ...)
res = res[order(res[, rstr]), ]
res[, rstr] = NULL
res
}
이것은 첫 번째 데이터 프레임의 순서를 유지하고 병합된 데이터 프레임의 행 수가 첫 번째 데이터 프레임과 동일하다고 가정합니다.추가 열 없이 깨끗한 데이터 프레임을 제공합니다.
패키지 개발자용
패키지 개발자로서 가능한 한 적은 수의 다른 패키지에 의존하기를 원합니다.패키지 개발자 IMHO에게 너무 자주 바뀌는 깔끔한 역기능.
의 가입 기능을 활용할 수 있도록 하기 위해서는dplyr
가져오기 없이 패키지dplyr
, 아래는 빠른 구현입니다.원래 정렬을 유지하고(OP에서 요청한 대로) 접합 열을 앞쪽으로 이동시키지 않습니다(이것은 또 다른 성가신 일입니다).merge()
).
left_join <- function(x, y, ...) {
merge_exec(x = x, y = y, all.x = TRUE, ...)
}
right_join <- function(x, y, ...) {
merge_exec(x = x, y = y, all.y = TRUE, ...)
}
inner_join <- function(x, y, ...) {
merge_exec(x = x, y = y, all = TRUE, ...)
}
full_join <- function(x, y, ...) {
merge_exec(x = x, y = y, ...)
}
# workhorse:
merge_exec <- function(x, y, ...) {
# set index
x$join_id_ <- 1:nrow(x)
# do the join
joined <- merge(x = x, y = y, sort = FALSE, ...)
# get suffices (yes, I prefer this over suffixes)
if ("suffixes" %in% names(list(...))) {
suffixes <- list(...)$suffixes
} else {
suffixes <- c("", "")
}
# get columns names in right order, so the 'by' column won't be forced first
cols <- unique(c(colnames(x),
paste0(colnames(x), suffixes[1]),
colnames(y),
paste0(colnames(y), suffixes[2])))
# get the original row and column index
joined[order(joined$join_id),
cols[cols %in% colnames(joined) & cols != "join_id_"]]
}
이 특정한 경우에 당신은 우리에게factor
콤팩트 염기 용액의 경우:
df.2$prob = factor(df.2$class,labels=df.1$prob)
df.2
# object class prob
# 1 A 2 0.7
# 2 B 1 0.5
# 3 D 2 0.7
# 4 F 3 0.3
# 5 C 1 0.5
일반적인 해결책은 아니지만, 다음과 같은 경우에 효과가 있습니다.
- 고유 값을 포함하는 룩업 테이블이 있습니다.
- 테이블을 새로 만들지 않고 업데이트하려는 경우
- 조회 테이블이 병합 열로 정렬됩니다.
- 룩업 테이블에 추가 레벨이 없습니다.
- 은 을 .
left_join
- 인자가 괜찮으시다면
1은 협상할 수 없습니다. 나머지는 우리가 할 수 있습니다.
df.3 <- df.2 # deal with 2.
df.1b <- df.1[order(df.1$class),] # deal with 3
df.1b <- df.1b[df.1$class %in% df.2$class,] # deal with 4.
df.3$prob = factor(df.3$class,labels=df.1b$prob)
df.3 <- df3[!is.na(df.3$prob),] # deal with 5. if you want an `inner join`
df.3$prob <- as.numeric(as.character(df.3$prob)) # deal with 6.
최고 등급의 답변은 원래 포스터가 원하는 대로 1열의 "클래스"를 생성하지 않습니다.OP가 df.2에서 열 순서 전환을 허용할 경우, 가능한 기본 R 비병합 한 줄 답변은 다음과 같습니다.
df.1 <- data.frame(class = c(1, 2, 3), prob = c(0.5, 0.7, 0.3))
df.2 <- data.frame(class = c(2, 1, 2, 3, 1), object = c('A', 'B', 'D', 'F', 'C'))
cbind(df.2, df.1[match(df.2$class, df.1$class), -1, drop = FALSE])
행에 묘사된 정보, 이름들이 마음에 듭니다.OP가 원하는 결과를 정확하게 복제하는 완전한 원-라이너는 다음과 같습니다.
data.frame(cbind(df.2, df.1[match(df.2$class, df.1$class), -1, drop = FALSE]),
row.names = NULL)
시간이 지남에 따라 개발 경로가 자주 다르기 때문에 패키지 개발자가 다른 패키지(또는 "verse")에 의존하는 것이 적을수록 좋다는 https://stackoverflow.com/users/4575331/ms-berends 의 의견에 동의합니다.
참고: 위의 원-라이너는 에 중복이 있을 경우 작동하지 않습니다.df.1$class
. 이를 극복할 수 있습니다.'outer'
그리고 더 일반적으로 베렌드 씨의 영리한 합병 후 리스크램블링 코드를 가진 루프.
간단한 부분 집합이 다음과 같은 몇 가지 용도로 사용됩니다.
# Use the key variable as row.names
row.names(df.1) = df.1$key
# Sort df.1 so that it's rows match df.2
df.3 = df.1[df.2$key, ]
# Create a data.frame with cariables from df.1 and (the sorted) df.2
df.4 = cbind(df.1, df.3)
이 코드는 df.2와 순서를 유지하고 df.1의 일치하는 데이터만 추가합니다.
변수를 하나만 추가할 경우,cbind()
is not required:
row.names(df.1) = df.1$key
df.2$data = df.1[df.2$key, "data"]
나도 같은 문제가 있었지만 새로운 열 'num'에 적용된 더미 벡터 c(1:5)를 사용했습니다.
df.2 <- data.frame(object = c('A', 'B', 'D', 'F', 'C'), class = c(2, 1, 2, 3, 1))
df.2$num <- c(1:5) # This range you can order in the last step.
dfm <- merge(df.2, df.1) # merged
dfm <- dfm[order(dfm$num),] # ascending order
베이스에서 더 효율적인 방법이 있을지도 모릅니다.이것은 기능으로 만들기에 꽤 간단할 것입니다.
varorder <- names(mydata) # --- Merge
mydata <- merge(mydata, otherData, by="commonVar")
restOfvars <- names(mydata[!(names(mydata) %in% varorder)])
mydata[c(varorder,restOfvars)]
언급URL : https://stackoverflow.com/questions/17878048/merge-two-data-frames-while-keeping-the-original-row-order
'programing' 카테고리의 다른 글
Android에서 스타일리시한 속성 선언 (0) | 2023.10.17 |
---|---|
MariaDb slow_query_log 환경 변수(도커 포함) (0) | 2023.10.17 |
Angularjs 데이터 저장소 모범 사례 (0) | 2023.10.17 |
JSLint 메시지:미사용변수 (0) | 2023.10.12 |
멀티 스레드 어플리케이션에서 errno를 안전하게 사용할 수 있는 방법이 있습니까? (0) | 2023.10.12 |