it-swarm-ko.tech

서로 다른 열 집합이있을 때 두 개의 데이터 프레임을 행별로 결합 (rbind)

동일한 열 집합이없는 두 개의 데이터 프레임을 행으로 바인딩 할 수 있습니까? 바인딩 후 일치하지 않는 열을 유지하기를 바라고 있습니다.

186
Btibert3

plyr 패키지의 rbind.fill가 사용자가 원하는 것일 수 있습니다.

191

보다 최근의 해결책은 dplyrbind_rows 함수를 사용하는 것입니다.이 함수는 smartbind보다 효율적입니다.

92
xiaodai

smartbind 패키지에서 gtools을 사용할 수 있습니다.

예:

library(gtools)
df1 <- data.frame(a = c(1:5), b = c(6:10))
df2 <- data.frame(a = c(11:15), b = c(16:20), c = LETTERS[1:5])
smartbind(df1, df2)
# result
     a  b    c
1.1  1  6 <NA>
1.2  2  7 <NA>
1.3  3  8 <NA>
1.4  4  9 <NA>
1.5  5 10 <NA>
2.1 11 16    A
2.2 12 17    B
2.3 13 18    C
2.4 14 19    D
2.5 15 20    E
45
neilfws

df1의 열이 df2 (열 이름 기준)의 하위 집합 인 경우 :

df3 <- rbind(df1, df2[, names(df1)])
35
Aaron Statham

data.table의 대안 :

library(data.table)
df1 = data.frame(a = c(1:5), b = c(6:10))
df2 = data.frame(a = c(11:15), b = c(16:20), c = LETTERS[1:5])
rbindlist(list(df1, df2), fill = TRUE)

rbind은 객체가 data.table 객체로 변환되는 한 data.table에서도 작동합니다.

rbind(setDT(df1), setDT(df2), fill=TRUE)

이 상황에서도 작동합니다. 두 개의 data.tables가 있고 목록을 작성하지 않으려는 경우이 방법이 더 좋습니다.

29
kdauria

기본 R 응답의 대부분은 하나의 data.frame에만 추가 열이 있거나 결과 data.frame이 열의 교차점을 갖는 상황을 해결합니다. OP는 쓰기 때문에 바인드 이후에 일치하지 않는 컬럼을 유지하기를 원한다.이 문제를 해결하기 위해 기본 R 메소드를 사용하는 대답은 아마도 가치가있다. 전기.

아래에서는 두 가지 기본 R 방법을 제시합니다. 원본 데이터를 변경하는 방법입니다. 프레임과 그렇지 않은 방법이 있습니다. 또한 비파괴 방식을 두 개 이상의 data.frames로 일반화하는 방법을 제공합니다.

먼저 샘플 데이터를 얻으십시오.

# sample data, variable c is in df1, variable d is in df2
df1 = data.frame(a=1:5, b=6:10, d=month.name[1:5])
df2 = data.frame(a=6:10, b=16:20, c = letters[8:12])

두 개의 data.frames, 원본 변경
rbind에서 두 data.frames의 모든 열을 유지하고 (오류가 발생하지 않고 함수가 작동하도록 허용), 누락 된 적절한 이름이 채워진 각 data.frame에 NA 열을 추가합니다. setdiff.

# fill in non-overlapping columns with NAs
df1[setdiff(names(df2), names(df1))] <- NA
df2[setdiff(names(df1), names(df2))] <- NA

자, rbind- 안에요.

rbind(df1, df2)
    a  b        d    c
1   1  6  January <NA>
2   2  7 February <NA>
3   3  8    March <NA>
4   4  9    April <NA>
5   5 10      May <NA>
6   6 16     <NA>    h
7   7 17     <NA>    i
8   8 18     <NA>    j
9   9 19     <NA>    k
10 10 20     <NA>    l

첫 번째 두 줄은 원래의 data.frames 인 df1과 df2를 변경하여 두 세트에 전체 열 집합을 추가합니다.


두 개의 data.frames, 원본을 변경하지 마십시오
원래의 data.frames를 그대로 남겨 두려면 먼저 다른 이름을 반복하고 c을 사용하여 data.frame과 함께 목록으로 연결되는 명명 된 벡터의 NAs를 반환합니다. 그런 다음 data.frame는 결과를 rbind에 대한 적절한 data.frame으로 변환합니다.

rbind(
  data.frame(c(df1, sapply(setdiff(names(df2), names(df1)), function(x) NA))),
  data.frame(c(df2, sapply(setdiff(names(df1), names(df2)), function(x) NA)))
)

많은 data.frames, 원본을 변경하지 마십시오
두 개 이상의 data.frames가있는 경우 다음을 수행 할 수 있습니다.

# put data.frames into list (dfs named df1, df2, df3, etc)
mydflist <- mget(ls(pattern="df\\d+")
# get all variable names
allNms <- unique(unlist(lapply(mydflist, names)))

# put em all together
do.call(rbind,
        lapply(mydflist,
               function(x) data.frame(c(x, sapply(setdiff(allNms, names(x)),
                                                  function(y) NA)))))

원본 데이터의 행 이름을 볼 수없는 경우가 더 좋을 수 있습니다. 프레임? 그럼 해.

do.call(rbind,
        c(lapply(mydflist,
                 function(x) data.frame(c(x, sapply(setdiff(allNms, names(x)),
                                                    function(y) NA)))),
          make.row.names=FALSE))
20
lmo

일반적인 열 이름을 가져올 수도 있습니다.

> cols <- intersect(colnames(df1), colnames(df2))
> rbind(df1[,cols], df2[,cols])
18
Jonathan Chang

뭔가 잘못된 것이 있으면 내 코드를 말해주기 때문에이 작업을 수행하는 함수를 작성했습니다. 이 함수는 일치하지 않는 열 이름과 형식이 일치하지 않는 경우 명시 적으로 알려줍니다. 그런 다음 어쨌든 data.frames를 결합하는 것이 최선의 방법입니다. 제한 사항은 한 번에 두 개의 data.frames 만 결합 할 수 있다는 것입니다.

### combines data frames (like rbind) but by matching column names
# columns without matches in the other data frame are still combined
# but with NA in the rows corresponding to the data frame without
# the variable
# A warning is issued if there is a type mismatch between columns of
# the same name and an attempt is made to combine the columns
combineByName <- function(A,B) {
    a.names <- names(A)
    b.names <- names(B)
    all.names <- union(a.names,b.names)
    print(paste("Number of columns:",length(all.names)))
    a.type <- NULL
    for (i in 1:ncol(A)) {
        a.type[i] <- typeof(A[,i])
    }
    b.type <- NULL
    for (i in 1:ncol(B)) {
        b.type[i] <- typeof(B[,i])
    }
    a_b.names <- names(A)[!names(A)%in%names(B)]
    b_a.names <- names(B)[!names(B)%in%names(A)]
    if (length(a_b.names)>0 | length(b_a.names)>0){
        print("Columns in data frame A but not in data frame B:")
        print(a_b.names)
        print("Columns in data frame B but not in data frame A:")
        print(b_a.names)
    } else if(a.names==b.names & a.type==b.type){
        C <- rbind(A,B)
        return(C)
    }
    C <- list()
    for(i in 1:length(all.names)) {
        l.a <- all.names[i]%in%a.names
        pos.a <- match(all.names[i],a.names)
        typ.a <- a.type[pos.a]
        l.b <- all.names[i]%in%b.names
        pos.b <- match(all.names[i],b.names)
        typ.b <- b.type[pos.b]
        if(l.a & l.b) {
            if(typ.a==typ.b) {
                vec <- c(A[,pos.a],B[,pos.b])
            } else {
                warning(c("Type mismatch in variable named: ",all.names[i],"\n"))
                vec <- try(c(A[,pos.a],B[,pos.b]))
            }
        } else if (l.a) {
            vec <- c(A[,pos.a],rep(NA,nrow(B)))
        } else {
            vec <- c(rep(NA,nrow(A)),B[,pos.b])
        }
        C[[i]] <- vec
    }
    names(C) <- all.names
    C <- as.data.frame(C)
    return(C)
}
6
user399470

설명서 만 있으면됩니다. 다음 형식으로 Stack 라이브러리와 해당 함수 Stack을 시도 할 수 있습니다.

Stack(df_1, df_2)

또한 대형 데이터 세트의 다른 방법보다 빠르다는 인상을 받았습니다.

2
Cro-Magnon

어쩌면 나는 완전히 당신의 질문을 잘못 읽었지만, "바인드 후 일치하지 않는 컬럼을 유지하기를 원합니다"는 SQL 쿼리와 비슷한 left join 또는 right join를 찾고 있다고 생각하게 만듭니다. R에는 SQL의 조인 테이블과 비슷한 왼쪽, 오른쪽 또는 내부 조인을 지정할 수있는 merge 함수가 있습니다.

이미이 주제에 대한 훌륭한 질문과 대답이 있습니다 : 병합 (병합) 데이터 프레임 (내부, 외부, 왼쪽, 오른쪽)

1
Chase

gtools/smartbind는 Dates와의 작업을 좋아하지 않았습니다. 왜냐하면 아마도 as.vectoring 이었기 때문입니다. 그래서 여기 내 해결책이 ...

sbind = function(x, y, fill=NA) {
    sbind.fill = function(d, cols){ 
        for(c in cols)
            d[[c]] = fill
        d
    }

    x = sbind.fill(x, setdiff(names(y),names(x)))
    y = sbind.fill(y, setdiff(names(x),names(y)))

    rbind(x, y)
}
1
aaron

sjmisc::add_rows()을 사용하는 dplyr::bind_rows() 을 사용할 수도 있지만 bind_rows()과 달리 add_rows()은 속성을 보존하므로 레이블이 지정된 데이터 에 유용합니다.

레이블이 지정된 데이터 세트로 다음 예제를 참조하십시오. frq()- 함수는 빈도 테이블에 값 레이블을 출력합니다. if 데이터에 레이블이 지정됩니다.

library(sjmisc)
library(dplyr)

data(efc)
# select two subsets, with some identical and else different columns
x1 <- efc %>% select(1:5) %>% slice(1:10)
x2 <- efc %>% select(3:7) %>% slice(11:20)

str(x1)
#> 'data.frame':    10 obs. of  5 variables:
#>  $ c12hour : num  16 148 70 168 168 16 161 110 28 40
#>   ..- attr(*, "label")= chr "average number of hours of care per week"
#>  $ e15relat: num  2 2 1 1 2 2 1 4 2 2
#>   ..- attr(*, "label")= chr "relationship to elder"
#>   ..- attr(*, "labels")= Named num  1 2 3 4 5 6 7 8
#>   .. ..- attr(*, "names")= chr  "spouse/partner" "child" "sibling" "daughter or son -in-law" ...
#>  $ e16sex  : num  2 2 2 2 2 2 1 2 2 2
#>   ..- attr(*, "label")= chr "elder's gender"
#>   ..- attr(*, "labels")= Named num  1 2
#>   .. ..- attr(*, "names")= chr  "male" "female"
#>  $ e17age  : num  83 88 82 67 84 85 74 87 79 83
#>   ..- attr(*, "label")= chr "elder' age"
#>  $ e42dep  : num  3 3 3 4 4 4 4 4 4 4
#>   ..- attr(*, "label")= chr "elder's dependency"
#>   ..- attr(*, "labels")= Named num  1 2 3 4
#>   .. ..- attr(*, "names")= chr  "independent" "slightly dependent" "moderately dependent" "severely dependent"

bind_rows(x1, x1) %>% frq(e42dep)
#> 
#> # e42dep <numeric> 
#> # total N=20  valid N=20  mean=3.70  sd=0.47
#>  
#>   val frq raw.prc valid.prc cum.prc
#>     3   6      30        30      30
#>     4  14      70        70     100
#>  <NA>   0       0        NA      NA

add_rows(x1, x1) %>% frq(e42dep)
#> 
#> # elder's dependency (e42dep) <numeric> 
#> # total N=20  valid N=20  mean=3.70  sd=0.47
#>  
#>  val                label frq raw.prc valid.prc cum.prc
#>    1          independent   0       0         0       0
#>    2   slightly dependent   0       0         0       0
#>    3 moderately dependent   6      30        30      30
#>    4   severely dependent  14      70        70     100
#>   NA                   NA   0       0        NA      NA
0
Daniel