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.frame
objects, 이 솔루션은 @mdsummer's 및 @wojciech-sobala보다 몇 배 빠릅니다.
d[rep(seq_len(nrow(d)), n), ]
위해서data.table
objects, @mdsummer's는 변환 후 위를 적용하는 것보다 조금 빠릅니다.data.frame
. 큰 경우에는 뒤집힐 수 있습니다..
전체 코드:
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
data.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
'programing' 카테고리의 다른 글
ES6 클래스 다중 상속 (0) | 2023.10.26 |
---|---|
C에서 자체 수정 코드를 작성하는 방법은? (0) | 2023.10.26 |
.xlsx에서 셀 색상 가져오기 (0) | 2023.10.26 |
MariaDB 데이터베이스에서 mediumblob 값 업데이트 실패 (0) | 2023.10.26 |
MySQL: 자동 증가 열이 있는 테이블에 삽입 후 예기치 않은 SELECT 결과 (0) | 2023.10.21 |