सवाल डेटा बार-बार दोहराएं


मेरे पास निम्न डेटा फ्रेम है

data.frame(a = c(1,2,3),b = c(1,2,3))
  a b
1 1 1
2 2 2
3 3 3

और मैं इसे चालू करना चाहता हूं

  a b
1 1 1
2 2 2
3 3 3
4 1 1
5 2 2
6 3 3
7 1 1
8 2 2
9 3 3

या इसे बार दोहराएं। क्या आर में ऐसा करने के लिए कोई आसान काम है? धन्यवाद!


44
2018-01-06 04:53


मूल




जवाब:


संपादित करें: बेहतर आधुनिक आर उत्तर में अपडेट किया गया।

आप उपयोग कर सकते हैं replicate(), फिर rbind परिणाम एक साथ वापस। Rownames स्वचालित रूप से 1: nrows से चलाने के लिए बदल जाते हैं।

d <- data.frame(a = c(1,2,3),b = c(1,2,3))
n <- 3
do.call("rbind", replicate(n, d, simplify = FALSE))

इंडेक्सिंग का उपयोग करने का एक और पारंपरिक तरीका है, लेकिन यहां राउनम बदलना काफी साफ नहीं है (लेकिन अधिक जानकारीपूर्ण):

 d[rep(seq_len(nrow(d)), n), ]

ऊपर दिए गए सुधारों में पहले दो सुधार हैं purrr कार्यात्मक प्रोग्रामिंग, idiomatic purrr:

purrr::map_df(seq_len(3), ~d)

और कम बेवकूफ purrr (समान परिणाम, हालांकि अधिक अजीब):

purrr::map_df(seq_len(3), function(x) d)

और अंत में सूची के बजाय अनुक्रमण के माध्यम से उपयोग लागू करें dplyr:

d %>% slice(rep(row_number(), 3))

79
2018-01-06 05:23



शून्य पंक्ति डेटा फ्रेम से सावधान रहें। seq_len शायद एक बेहतर विकल्प है - hadley
धन्यवाद, मैंने उस पर चिल्लाया (मुझे हमेशा लगता है कि यह seq_along है और प्रयास में नहीं डाल रहा था)। मैं सिर की सराहना करता हूं। - mdsumner


के लिये data.frame ऑब्जेक्ट्स, यह समाधान @ mdsummer और @ wojciech-sobala की तुलना में कई गुना तेज है।

d[rep(seq_len(nrow(d)), n), ]

के लिये data.table ऑब्जेक्ट्स, @ mdsummer का रूपांतरण करने के बाद उपरोक्त को लागू करने से थोड़ा तेज है data.frame। बड़े एन के लिए यह फ्लिप हो सकता है। microbenchmark

पूरा कोड:

Repeat1 <- function(d, n) {
  return(do.call("rbind", replicate(n, d, simplify = FALSE)))
}

Repeat2 <- function(d, n) {
  return(Reduce(rbind, list(d)[rep(1L, times=n)]))
}

Repeat3 <- function(d, n) {
  if ("data.table" %in% class(d)) return(d[rep(seq_len(nrow(d)), n)])
  return(d[rep(seq_len(nrow(d)), n), ])
}

Repeat3.dt.convert <- function(d, n) {
  if ("data.table" %in% class(d)) d <- as.data.frame(d)
  return(d[rep(seq_len(nrow(d)), n), ])
}

# Try with data.frames
mtcars1 <- Repeat1(mtcars, 3)
mtcars2 <- Repeat2(mtcars, 3)
mtcars3 <- Repeat3(mtcars, 3)

library(RUnit)
checkEquals(mtcars1, mtcars2)
#  Only difference is row.names having ".k" suffix instead of "k" from 1 & 2
checkEquals(mtcars1, mtcars3)

# Works with data.tables too
mtcars.dt <- data.table(mtcars)
mtcars.dt1 <- Repeat1(mtcars.dt, 3)
mtcars.dt2 <- Repeat2(mtcars.dt, 3)
mtcars.dt3 <- Repeat3(mtcars.dt, 3)

# No row.names mismatch since data.tables don't have row.names
checkEquals(mtcars.dt1, mtcars.dt2)
checkEquals(mtcars.dt1, mtcars.dt3)

# Time test
library(microbenchmark)
res <- microbenchmark(Repeat1(mtcars, 10),
                      Repeat2(mtcars, 10),
                      Repeat3(mtcars, 10),
                      Repeat1(mtcars.dt, 10),
                      Repeat2(mtcars.dt, 10),
                      Repeat3(mtcars.dt, 10),
                      Repeat3.dt.convert(mtcars.dt, 10))
print(res)
library(ggplot2)
ggsave("~/gdrive/repeat_microbenchmark.png", autoplot(res))

18
2018-02-13 18:55





पैकेज dplyr समारोह शामिल है bind_rows() जो किसी सूची में सभी डेटा फ्रेम को सीधे जोड़ता है, जैसे कि उपयोग करने की कोई आवश्यकता नहीं है do.call() के साथ साथ rbind():

df <- data.frame(a = c(1, 2, 3), b = c(1, 2, 3))
library(dplyr)
bind_rows(replicate(3, df, simplify = FALSE))

बड़ी संख्या में पुनरावृत्ति के लिए bind_rows() इससे भी तेज है rbind():

library(microbenchmark)
microbenchmark(rbind = do.call("rbind", replicate(1000, df, simplify = FALSE)),
               bind_rows = bind_rows(replicate(1000, df, simplify = FALSE)),
               times = 20)
## Unit: milliseconds
##       expr       min        lq      mean   median        uq       max neval cld
##      rbind 31.796100 33.017077 35.436753 34.32861 36.773017 43.556112    20   b
##  bind_rows  1.765956  1.818087  1.881697  1.86207  1.898839  2.321621    20  a 

9
2017-08-11 15:30



मेरा अनुमान slice(rep(row_number(), 3)) मैक्स के बेंचमार्क के मुकाबले बेहतर है। ओह, बस अपनी पीठ को देखा ... व्यक्तिगत रूप से, मुझे लगता है कि डीएफ के आकार को स्केल करना कुछ हद तक सही दिशा होगी, टेबल की संख्या के बजाय, लेकिन मुझे नहीं पता। - Frank
अच्छा है! जब मैं इसे बेंचमार्क करता हूं, slice(df, rep(row_number(), 3)) की तुलना में थोड़ा सा धीमा हो जाता है bind_rows(replicate(...)) (1.9 बनाम 2.1 एमएस)। किसी भी मामले में, मैंने सोचा कि यह एक उपयोगी है dplyr-साथ-साथ विकास भी ... - Stibu
@ फ्रैंक आप शायद सही हैं। मैंने जांच नहीं की कि बड़े डेटा फ्रेम के लिए क्या होता है, क्योंकि मैंने अभी प्रश्न में दिए गए एक का उपयोग किया था। - Stibu


d <- data.frame(a = c(1,2,3),b = c(1,2,3))
r <- Reduce(rbind, list(d)[rep(1L, times=3L)])

3
2018-01-06 19:34



आपने अभी क्या किया है और यह कैसे mdsumner के जवाब की तुलना में विस्तार से विस्तार करने की देखभाल करता है? शायद कुछ परिणामों में पेस्ट करें? - Roman Luštrik


दोहराव समारोह के साथ बस सरल अनुक्रमण का उपयोग करें।

mydata<-data.frame(a = c(1,2,3),b = c(1,2,3)) #creating your data frame  
n<-10           #defining no. of time you want repetition of the rows of your dataframe

mydata<-mydata[rep(rownames(mydata),n),] #use rep function while doing indexing 
rownames(mydata)<-1:NROW(mydata)    #rename rows just to get cleaner look of data

2
2018-04-01 11:22