gpt4 book ai didi

r - 重新排序行以具有重复序列的有效方法?

转载 作者:行者123 更新时间:2023-12-02 15:46:38 25 4
gpt4 key购买 nike

我有一个数据集,其中每个 name 值都重复了一定次数。我想对行重新排序,这样我就不会重复每个 name,而是重复整个序列。

例如,如果我有这样的数据集:

test <- data.frame(
name = rep(c("a", "b", "c"), each = 3),
value = 1:9
)

> test_data
name value
1 a 1
2 a 2
3 a 3
4 b 4
5 b 5
6 b 6
7 c 7
8 c 8
9 c 9

然后我想对行重新排序,这样我就有了 a-b-c 的重复序列:

  name value
1 a 1
2 b 4
3 c 7
4 a 2
5 b 5
6 c 8
7 a 3
8 b 6
9 c 9

这是我目前所拥有的:

# split by value in name
split_data <- split(test_data, ~ name)

# in each split dataset, create id2
list_data <- lapply(seq_along(split_data), function(x) {
new_id <- x + (1:nrow(split_data[[x]]) - 1) * length(split_data)
split_data[[x]]$id2 <- new_id
return(split_data[[x]])
})

# bind the split data back, and order by this new id2
out <- do.call(rbind, list_data)
out <- out[order(out$id2), ]
out$id2 <- NULL
out

name value
1 a 1
4 b 4
7 c 7
2 a 2
5 b 5
8 c 8
3 a 3
6 b 6
9 c 9

这行得通,但我现在正在寻找一种在时间和内存方面都更有效的方法。以下是具有几百万行的代码的性能:

test_data <- data.frame(
name = rep(c("a", "b", "c"), each = 1000000),
value = 1:3000000
)
dim(test_data)
#> [1] 3000000 2

my_test <- function() {
split_data <- split(test_data, ~ name)

list_data <- lapply(seq_along(split_data), function(x) {
new_id <- x + (1:nrow(split_data[[x]]) - 1) * length(split_data)
split_data[[x]]$id2 <- new_id
return(split_data[[x]])
})

out <- do.call(rbind, list_data)
out <- out[order(out$id2), ]
out$id2 <- NULL

}

bench::mark(
my_test()
)
#> Warning: Some expressions had a GC in every iteration; so filtering is disabled.
#> # A tibble: 1 × 6
#> expression min median `itr/sec` mem_alloc `gc/sec`
#> <bch:expr> <bch:tm> <bch:tm> <dbl> <bch:byt> <dbl>
#> 1 my_test() 907ms 907ms 1.10 541MB 7.72

有没有更有效的方法来做同样的事情?我正在寻找仅在 base R 中的解决方案。

注意:我为 value 放置了一个非常简单的数字序列。这只是为了举例。解决方案不应依赖于 value 中的值。

编辑以比较 Mael 的输出:

test_data <- data.frame(
name = rep(c("a", "b", "c"), each = 10),
value = 1:30
)

mael <- function() {
out <- test_data[order(ave(test_data$name, test_data$name, FUN = seq_along)), ]
row.names(out) <- NULL
out
}

head(my_test())
#> name value
#> 1 a 1
#> 2 b 11
#> 3 c 21
#> 4 a 2
#> 5 b 12
#> 6 c 22
head(mael())
#> name value
#> 1 a 1
#> 2 b 11
#> 3 c 21
#> 4 a 10
#> 5 b 20
#> 6 c 30

最佳答案

如果保证name的顺序:

test_data[c(matrix(seq_len(nrow(test_data)), 
nrow=length(unique(test_data$name)),
byrow=T)), ]

关于r - 重新排序行以具有重复序列的有效方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73984957/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com