使用 R 根据条件随机排列数据框中的行
Shuffle rows in a dataframe based on a condition using R
我正在尝试使用 R 根据条件随机排列数据框中的所有行。
这是我的数据框示例:
l <- c("Ana", "Maria", "Hanne", "Liam","Sarah","Ella")
c <- c(1,1,2,3,3,2)
df <- as.data.frame(cbind(l,c))
colnames(df) <- c("Name", "ClassNr")
我的目标是打乱所有行,确保 3 行的每个序列都具有来自不同 ClassNr 的名称。
我尝试了以下方法:
set.seed(55)
df[sample(nrow(df), 3),]
此代码给了我 3 个随机行,但我需要添加条件,即在 3 行的每个“块”中不重复给定的 ClassNr。此外,我需要再次重复此操作以将完整的名称列表包含在“随机数据框”中。
输出示例为:
Name ClassNr
1 Ana 1
2 Ella 2
3 Liam 3
4 Maria 1
5 Hanne 2
6 Sarah 3
解决这个问题的最佳方法是什么?
我曾尝试使用此示例,但未能理解解决方案以适用于我的问题:
谢谢
为什么不简单地打乱你的名字,然后将 1:3 的序列追加两次?但是我其实不太明白你要达到什么目的,所以也许你可以更清楚一点。
(注意:我在这里按字母顺序排列名称是为了说明,但这在现实生活中没有意义,因为它总是导致相同的结果)
set.seed(1)
Name <- sort(sample(l, 6, replace = FALSE))
ClassNr <- rep(1:3, 2)
shuffled_df <- data.frame(Name, ClassNr)
shuffled_df
Name ClassNr
1 Ana 1
2 Ella 2
3 Hanne 3
4 Liam 1
5 Maria 2
6 Sarah 3
这是一个相当简单的方法,但可能不是最短的方法。
library(dplyr)
l <- c("Ana", "Maria", "Hanne", "Liam","Sarah","Ella")
c <- c(1,1,2,3,3,2)
df <- as.data.frame(cbind(l,c))
colnames(df) <- c("Name", "ClassNr")
正在创建一个包含 3 个数据帧的列表 - 每个 class。此时在 3 个数据帧中的每一个中,行都被打乱。 index
列已添加以进一步排序:
lst = list()
for (i in unique(df$ClassNr)) {
dat <- df %>%
filter(ClassNr == i)
rows <- sample(nrow(dat))
dat <- dat[rows, ]
dat <- dat %>% mutate(index = row_number())
lst[[i]] = dat
}
将 3 个打乱的数据帧连接到最终的 output
数据帧中。按index
和ClassNr
排列:
output <- data.frame()
for (i in seq(1:length(lst))) {
output <- output %>% rbind(lst[[i]])
}
output <- output %>%
arrange(index, ClassNr) %>%
select(-index)
按index
排列确保1-2-3顺序。你可以这样想:用 Class 1 从 df 中取出第一行,用 Class 2 添加 df 的第一行,然后用 Class 3 添加第一行。然后添加第二行来自第一、第二和第三数据集等
结果:
Name ClassNr
2 Maria 1
21 Ella 2
22 Liam 3
1 Ana 1
11 Hanne 2
12 Sarah 3
你可以试试这个:
library(purrr)
library(tidyr)
library(dplyr)
df %>%
split(f = as.factor(.$ClassNr)) %>%
map_dfr(~sample(.x$Name)) %>%
pivot_longer(everything(),
names_to = "ClassNr",
values_to = "Name")
返回(例如)
# A tibble: 6 x 2
ClassNr Name
<chr> <chr>
1 1 Ana
2 2 Ella
3 3 Sarah
4 1 Maria
5 2 Hanne
6 3 Liam
- 我们首先根据 ClassNr 将数据分组。那是
split
部分。现在我们有三个列表(每个 class 一个列表)。
- 接下来我们获取每个列表并对元素进行采样,这基本上是独立地洗牌每个列表并将结果绑定在一起作为数据帧。
- 最后我们将这个数据帧转换为长格式。
注意:如果每个 class 中的名称数量不同,此方法很可能会失败。
我的解决方案是使用dplyr的arrange()
来排列ClassNr,然后排列在一个重复的数字序列上:
df %>%
arrange(ClassNr) %>%
arrange(rep(1:(ceiling(nrow(df)/3)), 3)[1:nrow(df)])
Name ClassNr
1 Ana 1
2 Hanne 2
3 Liam 3
4 Maria 1
5 Ella 2
6 Sarah 3
需要对排序序列进行一些操作,以防行数不能被 3 整除。例如:
Name ClassNr
1 Ana 1
2 Hanne 2
3 Liam 3
4 Maria 1
5 Ella 2
6 Sarah 3
7 Other 1
8 Other2 2
我正在尝试使用 R 根据条件随机排列数据框中的所有行。
这是我的数据框示例:
l <- c("Ana", "Maria", "Hanne", "Liam","Sarah","Ella")
c <- c(1,1,2,3,3,2)
df <- as.data.frame(cbind(l,c))
colnames(df) <- c("Name", "ClassNr")
我的目标是打乱所有行,确保 3 行的每个序列都具有来自不同 ClassNr 的名称。 我尝试了以下方法:
set.seed(55)
df[sample(nrow(df), 3),]
此代码给了我 3 个随机行,但我需要添加条件,即在 3 行的每个“块”中不重复给定的 ClassNr。此外,我需要再次重复此操作以将完整的名称列表包含在“随机数据框”中。
输出示例为:
Name ClassNr
1 Ana 1
2 Ella 2
3 Liam 3
4 Maria 1
5 Hanne 2
6 Sarah 3
解决这个问题的最佳方法是什么?
我曾尝试使用此示例,但未能理解解决方案以适用于我的问题:
谢谢
为什么不简单地打乱你的名字,然后将 1:3 的序列追加两次?但是我其实不太明白你要达到什么目的,所以也许你可以更清楚一点。
(注意:我在这里按字母顺序排列名称是为了说明,但这在现实生活中没有意义,因为它总是导致相同的结果)
set.seed(1)
Name <- sort(sample(l, 6, replace = FALSE))
ClassNr <- rep(1:3, 2)
shuffled_df <- data.frame(Name, ClassNr)
shuffled_df
Name ClassNr
1 Ana 1
2 Ella 2
3 Hanne 3
4 Liam 1
5 Maria 2
6 Sarah 3
这是一个相当简单的方法,但可能不是最短的方法。
library(dplyr)
l <- c("Ana", "Maria", "Hanne", "Liam","Sarah","Ella")
c <- c(1,1,2,3,3,2)
df <- as.data.frame(cbind(l,c))
colnames(df) <- c("Name", "ClassNr")
正在创建一个包含 3 个数据帧的列表 - 每个 class。此时在 3 个数据帧中的每一个中,行都被打乱。 index
列已添加以进一步排序:
lst = list()
for (i in unique(df$ClassNr)) {
dat <- df %>%
filter(ClassNr == i)
rows <- sample(nrow(dat))
dat <- dat[rows, ]
dat <- dat %>% mutate(index = row_number())
lst[[i]] = dat
}
将 3 个打乱的数据帧连接到最终的 output
数据帧中。按index
和ClassNr
排列:
output <- data.frame()
for (i in seq(1:length(lst))) {
output <- output %>% rbind(lst[[i]])
}
output <- output %>%
arrange(index, ClassNr) %>%
select(-index)
按index
排列确保1-2-3顺序。你可以这样想:用 Class 1 从 df 中取出第一行,用 Class 2 添加 df 的第一行,然后用 Class 3 添加第一行。然后添加第二行来自第一、第二和第三数据集等
结果:
Name ClassNr
2 Maria 1
21 Ella 2
22 Liam 3
1 Ana 1
11 Hanne 2
12 Sarah 3
你可以试试这个:
library(purrr)
library(tidyr)
library(dplyr)
df %>%
split(f = as.factor(.$ClassNr)) %>%
map_dfr(~sample(.x$Name)) %>%
pivot_longer(everything(),
names_to = "ClassNr",
values_to = "Name")
返回(例如)
# A tibble: 6 x 2
ClassNr Name
<chr> <chr>
1 1 Ana
2 2 Ella
3 3 Sarah
4 1 Maria
5 2 Hanne
6 3 Liam
- 我们首先根据 ClassNr 将数据分组。那是
split
部分。现在我们有三个列表(每个 class 一个列表)。 - 接下来我们获取每个列表并对元素进行采样,这基本上是独立地洗牌每个列表并将结果绑定在一起作为数据帧。
- 最后我们将这个数据帧转换为长格式。
注意:如果每个 class 中的名称数量不同,此方法很可能会失败。
我的解决方案是使用dplyr的arrange()
来排列ClassNr,然后排列在一个重复的数字序列上:
df %>%
arrange(ClassNr) %>%
arrange(rep(1:(ceiling(nrow(df)/3)), 3)[1:nrow(df)])
Name ClassNr
1 Ana 1
2 Hanne 2
3 Liam 3
4 Maria 1
5 Ella 2
6 Sarah 3
需要对排序序列进行一些操作,以防行数不能被 3 整除。例如:
Name ClassNr
1 Ana 1
2 Hanne 2
3 Liam 3
4 Maria 1
5 Ella 2
6 Sarah 3
7 Other 1
8 Other2 2