我的数据框如下所示:
library(dplyr)
df <- data.frame(grp = rep(letters[1:3], each = 3)) %>%
mutate(val = paste0(grp, 1:3))
grp val
1 a a1
2 a a2
3 a a3
4 b b1
5 b b2
6 b b3
7 c c1
8 c c2
9 c c3
我希望将df
的行顺序置换为grp
,这样每3个连续行必须按随机顺序包含a,b和c。以下是输出应如何显示的三个示例:
grp val grp val grp val
1 a a1 9 c c3 7 c c1
8 c c2 2 a a2 1 a a1
4 b b1 5 b b2 6 b b3
3 a a3 4 b b1 9 c c3
9 c c3 3 a a3 3 a a3
6 b b3 7 c c1 4 b b1
7 c c1 6 b b3 5 b b2
2 a a2 8 c c2 8 c c2
5 b b2 1 a a1 2 a a2
理想情况下,该解决方案也适用于以下形式的类似数据框:
df <- data.frame(grp = rep(letters[1:x], each = y)) %>%
mutate(val = paste0(grp, 1:(x*y)))
# where x and y may be natural numbers
我试图使用group_by
和sample_n
函数,但没有成功。
答案 0 :(得分:2)
这是一个dplyr方法:
df %>%
sample_frac(1) %>% # order randomly
group_by(grp) %>% # group by "grp" column
group_by(row = row_number()) %>% # group by 1:n in each "grp" group
sample_frac(1) # sample all rows from these groups
之后,您可以使用%>% ungroup() %>% select(-row)
扩展管道以删除新创建的分组列。
两次采样运行的结果如下
replicate(2, sample_frac(df, 1) %>% group_by(grp) %>%
group_by(row = row_number()) %>%
sample_frac(1), simplify = FALSE)
# [[1]]
# Source: local data frame [9 x 3]
# Groups: row [3]
#
# grp val row
# <fctr> <chr> <int>
# 1 b b1 1
# 2 c c1 1
# 3 a a2 1
# 4 a a1 2
# 5 c c2 2
# 6 b b2 2
# 7 b b3 3
# 8 c c3 3
# 9 a a3 3
#
# [[2]]
# Source: local data frame [9 x 3]
# Groups: row [3]
#
# grp val row
# <fctr> <chr> <int>
# 1 c c3 1
# 2 a a3 1
# 3 b b3 1
# 4 a a1 2
# 5 b b2 2
# 6 c c1 2
# 7 c c2 3
# 8 a a2 3
# 9 b b1 3
答案 1 :(得分:1)
以下是使用replicate
,sample
,rep
和t
的基本R方法。这假设组中的单元数与组数相同。
permuter <- function(n) c(t(replicate(n, sample(n))) + (rep(seq_len(n)-1) * n))
这使用replicate
来抽样每个组中的元素数量,从而有效地排序组内元素的选择。矩阵输出被添加到调整组数的序列中。由此产生的矩阵被转换为在组排序之间,然后转换为列出行的新位置的向量。
permuter(3)
[1] 1 5 7 2 6 9 3 4 8
要重新排序,只需将结果提供给[
。
df[permuter(3), ]
grp val
1 a a1
5 b b2
7 c c1
2 a a2
6 b b3
9 c c3
3 a a3
4 b b1
8 c c2
请注意,我使用set.seed(1234)
在两个实例中重现了该函数的相同输出。
更灵活的排列
在具有不同数量的组与组内大小(例如3组,每组有4个单元)的情况下,以下更灵活的功能将起作用。
permuterFlex <- function(numG, wSize) {
c(t(replicate(numG, sample(wSize)) + rep(seq_len(numG)-1, each=wSize) * (wSize)))
}
这里,numG是组的数量,wSize是组内的单位数。要查看此内容,请复制上述结果。
set.seed(1234)
permuterFlex(3, 3)
[1] 1 5 7 2 6 9 3 4 8