특정 행 인덱스에서 데이터 프레임에 새 행을 추가하지 않습니까?


160

다음 코드는 벡터를 데이터 프레임과 결합합니다.

newrow = c(1:4)
existingDF = rbind(existingDF,newrow)

그러나이 코드는 항상 데이터 프레임 끝에 새 행을 삽입합니다.

데이터 프레임 내에서 지정된 지점에 행을 삽입하려면 어떻게해야합니까? 예를 들어 데이터 프레임에 20 개의 행이 있다고 가정하면 행 10과 11 사이에 새 행을 삽입하려면 어떻게해야합니까?


편리한 색인을 사용하고 정렬 하시겠습니까?
Roland

22
existingDF = rbind(existingDF[1:10,],newrow,existingDF[-(1:10),])
Pop

간단한 루프와 필요한 경우 조건을 사용하여 한 데이터 프레임에서 다른 데이터 프레임으로 행을 추가 할 수 있습니다. 샘플 코드는 다음과 같습니다newdataframe[nrow(newdataframe)+1,] <- existingdataframe[i,]
kirancodify at

답변:


156

다음은 (종종 느린) rbind호출 을 피하는 솔루션입니다 .

existingDF <- as.data.frame(matrix(seq(20),nrow=5,ncol=4))
r <- 3
newrow <- seq(4)
insertRow <- function(existingDF, newrow, r) {
  existingDF[seq(r+1,nrow(existingDF)+1),] <- existingDF[seq(r,nrow(existingDF)),]
  existingDF[r,] <- newrow
  existingDF
}

> insertRow(existingDF, newrow, r)
  V1 V2 V3 V4
1  1  6 11 16
2  2  7 12 17
3  1  2  3  4
4  3  8 13 18
5  4  9 14 19
6  5 10 15 20

속도가 선명도보다 중요하지 않으면 @Simon의 솔루션이 효과적입니다.

existingDF <- rbind(existingDF[1:r,],newrow,existingDF[-(1:r),])
> existingDF
   V1 V2 V3 V4
1   1  6 11 16
2   2  7 12 17
3   3  8 13 18
4   1  2  3  4
41  4  9 14 19
5   5 10 15 20

(우리는 r다르게 색인 합니다).

그리고 마지막으로 벤치 마크 :

library(microbenchmark)
microbenchmark(
  rbind(existingDF[1:r,],newrow,existingDF[-(1:r),]),
  insertRow(existingDF,newrow,r)
)

Unit: microseconds
                                                    expr     min       lq   median       uq       max
1                       insertRow(existingDF, newrow, r) 660.131 678.3675 695.5515 725.2775   928.299
2 rbind(existingDF[1:r, ], newrow, existingDF[-(1:r), ]) 801.161 831.7730 854.6320 881.6560 10641.417

벤치 마크

@MatthewDowle이 항상 지적했듯이 문제의 크기가 증가함에 따라 벤치마킹을 통해 스케일링을 검사해야합니다. 여기 우리는 간다 :

benchmarkInsertionSolutions <- function(nrow=5,ncol=4) {
  existingDF <- as.data.frame(matrix(seq(nrow*ncol),nrow=nrow,ncol=ncol))
  r <- 3 # Row to insert into
  newrow <- seq(ncol)
  m <- microbenchmark(
   rbind(existingDF[1:r,],newrow,existingDF[-(1:r),]),
   insertRow(existingDF,newrow,r),
   insertRow2(existingDF,newrow,r)
  )
  # Now return the median times
  mediansBy <- by(m$time,m$expr, FUN=median)
  res <- as.numeric(mediansBy)
  names(res) <- names(mediansBy)
  res
}
nrows <- 5*10^(0:5)
benchmarks <- sapply(nrows,benchmarkInsertionSolutions)
colnames(benchmarks) <- as.character(nrows)
ggplot( melt(benchmarks), aes(x=Var2,y=value,colour=Var1) ) + geom_line() + scale_x_log10() + scale_y_log10()

@Roland의 솔루션은 다음을 호출하더라도 상당히 잘 확장됩니다 rbind.

                                                              5       50     500    5000    50000     5e+05
insertRow2(existingDF, newrow, r)                      549861.5 579579.0  789452 2512926 46994560 414790214
insertRow(existingDF, newrow, r)                       895401.0 905318.5 1168201 2603926 39765358 392904851
rbind(existingDF[1:r, ], newrow, existingDF[-(1:r), ]) 787218.0 814979.0 1263886 5591880 63351247 829650894

선형 척도로 표시 :

선의

그리고 로그 로그 스케일 :

로그-로그


3
끝에 행을 삽입하면 이상한 동작이 발생합니다!
Maarten

@Maarten 어떤 기능을 사용합니까?
Ari B. Friedman

나는 내가 여기 설명하고있어 같은 이상한 행동을 것 같아요 : stackoverflow.com/questions/19927806/...
PatrickT

1
내 특정 데이터 프레임 및 행에서 insertRow2에서 이상한 동작이 발생하지 않습니다.
PatrickT

df에 숫자 행을 어떻게 추가합니까? 나는이 df열이 a,b,c,d나는 행을 추가 할 1,2,3,4. 어떻게합니까?
트래비스 Heeter

44
insertRow2 <- function(existingDF, newrow, r) {
  existingDF <- rbind(existingDF,newrow)
  existingDF <- existingDF[order(c(1:(nrow(existingDF)-1),r-0.5)),]
  row.names(existingDF) <- 1:nrow(existingDF)
  return(existingDF)  
}

insertRow2(existingDF,newrow,r)

  V1 V2 V3 V4
1  1  6 11 16
2  2  7 12 17
3  1  2  3  4
4  3  8 13 18
5  4  9 14 19
6  5 10 15 20

microbenchmark(
+   rbind(existingDF[1:r,],newrow,existingDF[-(1:r),]),
+   insertRow(existingDF,newrow,r),
+   insertRow2(existingDF,newrow,r)
+ )
Unit: microseconds
                                                    expr     min       lq   median       uq      max
1                       insertRow(existingDF, newrow, r) 513.157 525.6730 531.8715 544.4575 1409.553
2                      insertRow2(existingDF, newrow, r) 430.664 443.9010 450.0570 461.3415  499.988
3 rbind(existingDF[1:r, ], newrow, existingDF[-(1:r), ]) 606.822 625.2485 633.3710 653.1500 1489.216

3
이것은 멋진 솔루션입니다. 여전히 너무 빨리에 동시 호출보다는 왜 알아낼 수 없습니다 rbind,하지만 난 흥미 있어요.
Ari B. Friedman

벤치 마크가있는 답변에는 IMO가 자동으로 적용됩니다. 감사!
Alex

10

dplyr 패키지를 사용해보십시오

library(dplyr)
a <- data.frame(A = c(1, 2, 3, 4),
               B = c(11, 12, 13, 14))


system.time({
for (i in 50:1000) {
    b <- data.frame(A = i, B = i * i)
    a <- bind_rows(a, b)
}

})

산출

   user  system elapsed 
   0.25    0.00    0.25

rbind 함수를 사용하는 것과 달리

a <- data.frame(A = c(1, 2, 3, 4),
                B = c(11, 12, 13, 14))


system.time({
    for (i in 50:1000) {
        b <- data.frame(A = i, B = i * i)
        a <- rbind(a, b)
    }

})

산출

   user  system elapsed 
   0.49    0.00    0.49 

약간의 성능 향상이 있습니다.


-4

예를 들어 "edges"라는 데이터의 변수 1에 변수 2의 행을 추가하려면 다음과 같이하십시오.

allEdges <- data.frame(c(edges$V1,edges$V2))
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.