SORU
19 Temmuz 2012, PERŞEMBE


Yeni satır dataframe Ekle

Aşağıdaki kodu bir dataframe ile bir vektörü ifade etmektedir

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

Ancak bu kod her zaman dataframe sonunda yeni bir satır ekler.

Nasıl dataframe içinde belirli bir noktada satır ekleyebilir miyim? Örneğin, dataframe 20 satır var ki, nasıl satır 10 ve 11 arasında yeni bir satır ekleme yapabilir miyim sağlar?

CEVAP
19 Temmuz 2012, PERŞEMBE


Burada (genellikle yavaş) rbind çağrı kaçınan bir çözüm:

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

Eğer hızlı netlik daha az önemli ise, o zaman @Simon çözüm iyi çalışıyor:

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

(Bizim Endeksi 10* *farklı) not.

Ve son olarak, kriterler:

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

Kriterler

@MatthewDowle benim için her zaman işaret ettiği gibi, kriterler problemin boyutu arttıkça Ölçekleme için muayene edilmesi gerekiyor. Tamam, başlıyoruz:

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'ın çözüm oldukça iyi, rbind çağrı bile ölçekler:

                                                              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

Doğrusal bir ölçekte çizilen:

linear

Ve bir log-log ölçekli:

log-log

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • EmbarkToHeaven

    EmbarkToHeav

    3 EYLÜL 2007
  • Mark Halberstadt

    Mark Halbers

    19 ŞUBAT 2010
  • TechRax

    TechRax

    21 EYLÜL 2009