डेटाफ़्रेम में नई पंक्ति जोड़ें, विशिष्ट पंक्ति-सूचकांक में, संलग्न नहीं है?


160

निम्न कोड एक वेक्टर को डेटाफ्रेम के साथ जोड़ता है:

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

हालाँकि यह कोड हमेशा डेटाफ़्रेम के अंत में नई पंक्ति सम्मिलित करता है।

मैं डेटाफ्रेम के भीतर एक निर्दिष्ट बिंदु पर पंक्ति कैसे डाल सकता हूं? उदाहरण के लिए, मान लें कि डेटाफ्रेम में 20 पंक्तियां हैं, मैं पंक्तियों 10 और 11 के बीच नई पंक्ति कैसे डाल सकता हूं?


एक सुविधाजनक सूचकांक और सॉर्ट का उपयोग करें?
रोलैंड

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

एक साधारण लूप और यदि आवश्यक हो तो एक शर्त के साथ, पंक्तियों को एक डेटाफ्रेम से दूसरे में जोड़ा जा सकता है। एक नमूना कोड नीचे दिखाया गया हैnewdataframe[nrow(newdataframe)+1,] <- existingdataframe[i,]
kirancodify

जवाबों:


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

यदि गति स्पष्टता से कम महत्वपूर्ण है, तो @ साइमन का समाधान अच्छी तरह से काम करता है:

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()

@ रोलांड का समाधान बहुत अच्छी तरह से, यहां तक ​​कि कॉल के साथ 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 किस फंक्शन के साथ?
अरी बी। फ्रीडमैन

मुझे लगता है कि यह वही अजीब व्यवहार है जिसका मैं यहां वर्णन कर रहा हूं: stackoverflow.com/questions/19927806/…
पैट्रिकटी

1
मेरे विशेष डेटा फ़्रेम और पंक्ति में, InsertRow2 के साथ अजीब व्यवहार नहीं होता है।
पैट्रिक

आप केवल df में संख्याओं की एक पंक्ति को कैसे जोड़ते हैं? मेरे पास dfकॉलम हैं a,b,c,dऔर मैं पंक्ति जोड़ना चाहता हूं 1,2,3,4। मैं उसको कैसे करू?
बजे ट्रैविस हेटर

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, लेकिन मैं अंतर्विरोधी हूं।
अरी बी। फ्रीडमैन

मानदंड के साथ उत्तर में कुछ अतिरिक्त प्रतिष्ठा होनी चाहिए जो स्वचालित रूप से आईएमओ पर लागू होती है। धन्यवाद!
एलेक्स

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

उदाहरण के लिए आप "किनारों" नामक डेटा के चर 2 से चर 1 में जोड़ना चाहते हैं, बस इसे इस तरह से करें

allEdges <- data.frame(c(edges$V1,edges$V2))
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.