base::ifelse() within dplyr::arrange() 用于分组行的条件排列
base::ifelse() within dplyr::arrange() for conditional arrangement of grouped rows
我正在尝试根据另一列的值对 data.frame 的行进行排序。
下面是一个例子:
library(magrittr)
library(dplyr)
df <- data.frame(grp = c(1,1,1,2,2,2),
ori = c("f","f","f","r","r","r"),
ite = c("A","B","C","A","B","C"))
df
# # grp ori ite
# 1 1 f A
# 2 1 f B
# 3 1 f C
# 4 2 r A
# 5 2 r B
# 6 2 r C
df %>%
group_by(grp) %>%
arrange(ifelse(ori == "f", ite, desc(ite)), .by_group = TRUE) %>%
ungroup()
# # A tibble: 6 × 3
# # Groups: grp [2]
# grp ori ite
# <dbl> <chr> <chr>
# 1 1 f A
# 2 1 f B
# 3 1 f C
# 4 2 r A
# 5 2 r B
# 6 2 r C
预期输出为:
# # grp ori ite
# 1 1 f A
# 2 1 f B
# 3 1 f C
# 4 2 r C
# 5 2 r B
# 6 2 r A
我对它不起作用的原因有一个大概的了解:arrange()
不能逐行查看事物,而这正是 ifelse()
要求它做的。
有没有更好的方法来完成这个?
实现您想要的结果的一个选择是使用 split
+ arrange
+ bind_rows
像这样:
library(dplyr)
library(purrr)
df %>%
split(.$ori) %>%
purrr::imap(
~ if (.y == "f") arrange(.x, grp, ite) else arrange(.x, grp, desc(ite))
) %>%
dplyr::bind_rows()
#> grp ori ite
#> 1 1 f A
#> 2 1 f B
#> 3 1 f C
#> 4 2 r C
#> 5 2 r B
#> 6 2 r A
感谢@MartinGal 的建议,我们可以通过使用 purrr::imap_dfr
:
来节省 bind_rows
步骤
df %>%
split(.$ori) %>%
purrr::imap_dfr(
~ if (.y == "f") arrange(.x, grp, ite) else arrange(.x, grp, desc(ite))
)
一种可能的方法是拆分列 ori
并创建一个函数,然后按如下方式合并结果:
df %>%
split(.$ori) %>%
map(function(x) {
if ('f' %in% x$ori) {
x %>%
group_by(grp) %>%
arrange(ite, .by_group = TRUE)
}
else {
x %>%
group_by(grp) %>%
arrange(desc(ite), .by_group = TRUE)
}
}) %>%
bind_rows()
# A tibble: 6 x 3
## Groups: grp [2]
# grp ori ite
# <dbl> <chr> <chr>
#1 1 f A
#2 1 f B
#3 1 f C
#4 2 r C
#5 2 r B
#6 2 r A
这是另一个解决方案。
df %>%
arrange(
ifelse(ori == 'f', ite, NA),
desc(ifelse(ori != 'f', ite, NA))
)
使用ifelse(ori == "f", ite, desc(ite))
的想法基本上是好的,不幸的是desc(ite)
的输出是一个负数值向量,而ite
的输出是一个字符向量。要使用与输入相同的输出以相反的顺序带来 ite
的结果,我们可以将其包装在 base::rev
中而不是 dplyr::desc
.
library(dplyr)
df <- data.frame(grp = c(1,1,1,2,2,2),
ori = c("f","f","f","r","r","r"),
ite = c("A","B","C","A","B","C"))
df %>%
arrange(ori, ifelse(ori == "r", rev(ite), ite))
#> grp ori ite
#> 1 1 f A
#> 2 1 f B
#> 3 1 f C
#> 4 2 r C
#> 5 2 r B
#> 6 2 r A
由 reprex package (v0.3.0)
于 2021-09-18 创建
我正在尝试根据另一列的值对 data.frame 的行进行排序。
下面是一个例子:
library(magrittr)
library(dplyr)
df <- data.frame(grp = c(1,1,1,2,2,2),
ori = c("f","f","f","r","r","r"),
ite = c("A","B","C","A","B","C"))
df
# # grp ori ite
# 1 1 f A
# 2 1 f B
# 3 1 f C
# 4 2 r A
# 5 2 r B
# 6 2 r C
df %>%
group_by(grp) %>%
arrange(ifelse(ori == "f", ite, desc(ite)), .by_group = TRUE) %>%
ungroup()
# # A tibble: 6 × 3
# # Groups: grp [2]
# grp ori ite
# <dbl> <chr> <chr>
# 1 1 f A
# 2 1 f B
# 3 1 f C
# 4 2 r A
# 5 2 r B
# 6 2 r C
预期输出为:
# # grp ori ite
# 1 1 f A
# 2 1 f B
# 3 1 f C
# 4 2 r C
# 5 2 r B
# 6 2 r A
我对它不起作用的原因有一个大概的了解:arrange()
不能逐行查看事物,而这正是 ifelse()
要求它做的。
有没有更好的方法来完成这个?
实现您想要的结果的一个选择是使用 split
+ arrange
+ bind_rows
像这样:
library(dplyr)
library(purrr)
df %>%
split(.$ori) %>%
purrr::imap(
~ if (.y == "f") arrange(.x, grp, ite) else arrange(.x, grp, desc(ite))
) %>%
dplyr::bind_rows()
#> grp ori ite
#> 1 1 f A
#> 2 1 f B
#> 3 1 f C
#> 4 2 r C
#> 5 2 r B
#> 6 2 r A
感谢@MartinGal 的建议,我们可以通过使用 purrr::imap_dfr
:
bind_rows
步骤
df %>%
split(.$ori) %>%
purrr::imap_dfr(
~ if (.y == "f") arrange(.x, grp, ite) else arrange(.x, grp, desc(ite))
)
一种可能的方法是拆分列 ori
并创建一个函数,然后按如下方式合并结果:
df %>%
split(.$ori) %>%
map(function(x) {
if ('f' %in% x$ori) {
x %>%
group_by(grp) %>%
arrange(ite, .by_group = TRUE)
}
else {
x %>%
group_by(grp) %>%
arrange(desc(ite), .by_group = TRUE)
}
}) %>%
bind_rows()
# A tibble: 6 x 3
## Groups: grp [2]
# grp ori ite
# <dbl> <chr> <chr>
#1 1 f A
#2 1 f B
#3 1 f C
#4 2 r C
#5 2 r B
#6 2 r A
这是另一个解决方案。
df %>%
arrange(
ifelse(ori == 'f', ite, NA),
desc(ifelse(ori != 'f', ite, NA))
)
使用ifelse(ori == "f", ite, desc(ite))
的想法基本上是好的,不幸的是desc(ite)
的输出是一个负数值向量,而ite
的输出是一个字符向量。要使用与输入相同的输出以相反的顺序带来 ite
的结果,我们可以将其包装在 base::rev
中而不是 dplyr::desc
.
library(dplyr)
df <- data.frame(grp = c(1,1,1,2,2,2),
ori = c("f","f","f","r","r","r"),
ite = c("A","B","C","A","B","C"))
df %>%
arrange(ori, ifelse(ori == "r", rev(ite), ite))
#> grp ori ite
#> 1 1 f A
#> 2 1 f B
#> 3 1 f C
#> 4 2 r C
#> 5 2 r B
#> 6 2 r A
由 reprex package (v0.3.0)
于 2021-09-18 创建