programing

data.frame 행을 N번 반복합니다.

oldcodes 2023. 10. 26. 21:39
반응형

data.frame 행을 N번 반복합니다.

데이터 프레임은 다음과 같습니다.

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

행을 n번 반복하고 싶습니다.예를 들어, 여기서 행은 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

이것을 R에서 쉽게 할 수 있는 기능이 있습니까?감사합니다!

EDIT: 더 나은 현대적인 R 답변으로 업데이트.

사용가능replicate(),그리고나서rbind결과를 다시 합치다행 이름이 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기능적 프로그래밍, 관용적 purrr:

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

그리고 관용적인 purrr(identical 결과는 더 어색하지만)을 덜합니다.

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

그리고 마지막으로 목록이 아닌 색인을 통해 다음을 사용하여 적용합니다.dplyr:

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

위해서data.frameobjects, 이 솔루션은 @mdsummer's 및 @wojciech-sobala보다 몇 배 빠릅니다.

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

위해서data.tableobjects, @mdsummer's는 변환 후 위를 적용하는 것보다 조금 빠릅니다.data.frame. 큰 경우에는 뒤집힐 수 있습니다.microbenchmark.

전체 코드:

packages <- c("data.table", "ggplot2", "RUnit", "microbenchmark")
lapply(packages, require, character.only=T)

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)

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
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)
ggsave("repeat_microbenchmark.png", autoplot(res))

꾸러미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 

table-package를 사용하면 특별한 기호를 사용할 수 있습니다..I와 함께rep:

df <- data.frame(a = c(1,2,3), b = c(1,2,3))
dt <- as.data.table(df)

n <- 3

dt[rep(dt[, .I], n)]

다음을 제공합니다.

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

더욱 간단해진 기능:

library(data.table)
my_data <- data.frame(a = c(1,2,3),b = c(1,2,3))
rbindlist(replicate(n = 3, expr = my_data, simplify = FALSE)

반복 기능이 있는 단순 색인만 사용하면 됩니다.

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

시간 실행을 위해, 는 다른 방식의 rbind를 비교하는 것을 제안하고자 합니다.

> mydata <- data.frame(a=1:200,b=201:400,c=301:500)
> microbenchmark(rbind = do.call("rbind",replicate(n=100,mydata,simplify = FALSE)),
+                bind_rows = bind_rows(replicate(n=100,mydata,simplify = FALSE)),
+                rbindlist = rbindlist(replicate(n=100,exp= mydata,simplify = FALSE)),
+                times= 2000)
Unit: microseconds
      expr    min      lq      mean  median      uq      max neval
     rbind 5760.7 6723.10 8642.6930 7132.30 7761.05 240720.3  2000
 bind_rows  976.4 1186.90 1430.7741 1308.85 1469.80  15817.9  2000
 rbindlist  263.6  347.85  465.5894  392.90  459.95  10974.2  2000

단순한dplyr행당 반복실험 횟수를 다른 열로 변경할 수 있는 방법은 다음과 같습니다.

> exdf <- data.frame(id = LETTERS[1:6],
+                    blue1 = c(T,T,T,T,T,T),
+                    blue2 = c(T,T,F,F,T,T),
+                    red1 = c(T,F,T,F,T,F),
+                    red2 = c(F,F,T,F,F,F),
+                    n_times = 1:6)
> 
> exdf
  id blue1 blue2  red1  red2 n_times
1  A  TRUE  TRUE  TRUE FALSE       1
2  B  TRUE  TRUE FALSE FALSE       2
3  C  TRUE FALSE  TRUE  TRUE       3
4  D  TRUE FALSE FALSE FALSE       4
5  E  TRUE  TRUE  TRUE FALSE       5
6  F  TRUE  TRUE FALSE FALSE       6
> 
> exdf %>% slice(rep(seq(n()), n_times))
   id blue1 blue2  red1  red2 n_times
1   A  TRUE  TRUE  TRUE FALSE       1
2   B  TRUE  TRUE FALSE FALSE       2
3   B  TRUE  TRUE FALSE FALSE       2
4   C  TRUE FALSE  TRUE  TRUE       3
5   C  TRUE FALSE  TRUE  TRUE       3
6   C  TRUE FALSE  TRUE  TRUE       3
7   D  TRUE FALSE FALSE FALSE       4
8   D  TRUE FALSE FALSE FALSE       4
9   D  TRUE FALSE FALSE FALSE       4
10  D  TRUE FALSE FALSE FALSE       4
11  E  TRUE  TRUE  TRUE FALSE       5
12  E  TRUE  TRUE  TRUE FALSE       5
13  E  TRUE  TRUE  TRUE FALSE       5
14  E  TRUE  TRUE  TRUE FALSE       5
15  E  TRUE  TRUE  TRUE FALSE       5
16  F  TRUE  TRUE FALSE FALSE       6
17  F  TRUE  TRUE FALSE FALSE       6
18  F  TRUE  TRUE FALSE FALSE       6
19  F  TRUE  TRUE FALSE FALSE       6
20  F  TRUE  TRUE FALSE FALSE       6
21  F  TRUE  TRUE FALSE FALSE       6

물론 같은 값을 원하시면서 사용을 생략하셨다면"n_times"그냥 그 자리에서 정태적인 숫자를 선택할 수 있습니다.다른 사람이 이미...exdf %>% slice(rep(seq(n()), 4))모든 행을 4번 복제합니다.

사용가능tidyr::uncount:

data.frame(a = c(1,2,3),b = c(1,2,3)) %>% 
  tidyr::uncount(3)
  a b
1 1 1
2 1 1
3 1 1
4 2 2
5 2 2
6 2 2
7 3 3
8 3 3
9 3 3

데이터 테이블용

    dt[,.SD[rep(.I,n)]]
    dt[,.SD[rep(.I,each=n)]]

data.frame의 경우(로우네임과 관련된 일부 문제)

    df[rep(1:nrow(df),n),]
    df[rep(1:nrow(df),each=n),]

n반복 횟수

언급URL : https://stackoverflow.com/questions/8753531/repeat-rows-of-a-data-frame-n-times

반응형