将几块列动态移动到另一个位置
Move several chunks of columns dynamically to another position
我的数据是:
df <- data.frame(a = 1:2,
x = 1:2,
b = 1:2,
y = 3:4,
x_2 = 1:2,
y_2 = 3:4,
c = 1:2,
x_3 = 5:6,
y_3 = 1:2)
我现在想将 x 变量和 y 变量放在一起,以便列的顺序为:
a, x, x_2, x_3, b, y, y_2, y_3, c
我想,我可以将 tidyverse 的 relocate
函数与 lapply 或 map 或 reduce (?) 结合使用,但没有成功。
例如如果我这样做:
move_names <- c("x", "y")
library(tidyverse)
moved_data <- lapply(as.list(move_names), function(x)
{
df <- df |>
relocate(!!!syms(paste0(x, "_", 2:3)),
.after = all_of(x))
}
)
它分别移动 x 和 y,但它创建了单独的列表,但我只想拥有带有重定位列的原始 df。
更新:
我应该清楚我的真实数据框有大约 500 列,其中到处都是要移动的列。因此,提供所需列名顺序的完整向量是不可行的。
我拥有的是:我有原始列的名称,即 x 和 y,我有要移动的列的名称,即 x_2、x_3 , y_2, y_3.
不确定这是否是您想要的。
具有列名顺序的向量
假设您有一个包含列顺序的向量 relocate_name
:
library(tidyverse)
relocate_name <- c("a", "x", "x_2", "x_3", "b", "y", "y_2", "y_3", "c")
df %>% relocate(any_of(relocate_name))
带有列名前缀的向量
或者如果你只有订单的前缀,我们就称它为relocate_name2
:
relocate_name2 <- c("a", "x", "b", "y", "c")
df %>% relocate(starts_with(relocate_name2))
将 x 和 y 组合在一起
或者如果您只想将 x
和 y
“组合”在一起:
df %>%
relocate(starts_with("x"), .after = "x") %>%
relocate(starts_with("y"), .after = "y")
输出
以上输出都是一样的
a x x_2 x_3 b y y_2 y_3 c
1 1 1 1 5 1 3 3 1 1
2 2 2 2 6 2 4 4 2 2
library(rlist)
# split based in colname-part before _
L <- split.default(df, f = gsub("(.*)_.*", "\1", names(df)))
# remove names with an underscore
# this is the new order, it should match the names of list L !!
neworder <- names(df)[!grepl("_", names(df))]
# [1] "a" "x" "b" "y" "c"
# cbind list elements together
ans <- rlist::list.cbind(L[neworder])
# a x.x x.x_2 x.x_3 b y.y y.y_2 y.y_3 c
# 1 1 1 1 5 1 3 3 1 1
# 2 2 2 2 6 2 4 4 2 2
# create tidy names again
names(ans) <- gsub(".*\.(.*)", "\1", names(ans))
# a x x_2 x_3 b y y_2 y_3 c
# 1 1 1 1 5 1 3 3 1 1
# 2 2 2 2 6 2 4 4 2 2
在基数 R 中:
df[match(c('a', 'x', 'x_2', 'x_3', 'b', 'y', 'y_2', 'y_3', 'c'), names(df))]
#> a x x_2 x_3 b y y_2 y_3 c
#> 1 1 1 1 5 1 3 3 1 1
#> 2 2 2 2 6 2 4 4 2 2
好吧,这可能是有史以来最糟糕的解决方法,我真的不明白我到底在做什么(尤其是 <<-
),但它确实有效。
在你们这里的帮助下更多地意识到问题后,我的一般想法是“循环”我的 x 和 y 名称,从列名称向量中删除这些新的 _2 和 _3 列,然后re-append 他们在他们的“基础”x 和 y 列之后。
search_names <- c("x", "y")
df_names <- names(df)
new_names <- lapply(search_names, function(x)
{
start <- which(df_names == x)
without_new_names <- setdiff(df_names, paste0(x, "_", 2:3))
df_names <<- append(without_new_names, values = paste0(x, "_", 2:3), after = start)
})[[length(search_names)]]
df |>
relocate(any_of(new_names))
a x x_2 x_3 b y y_2 y_3 c
1 1 1 1 5 1 3 3 1 1
2 2 2 2 6 2 4 4 2 2
我的数据是:
df <- data.frame(a = 1:2,
x = 1:2,
b = 1:2,
y = 3:4,
x_2 = 1:2,
y_2 = 3:4,
c = 1:2,
x_3 = 5:6,
y_3 = 1:2)
我现在想将 x 变量和 y 变量放在一起,以便列的顺序为:
a, x, x_2, x_3, b, y, y_2, y_3, c
我想,我可以将 tidyverse 的 relocate
函数与 lapply 或 map 或 reduce (?) 结合使用,但没有成功。
例如如果我这样做:
move_names <- c("x", "y")
library(tidyverse)
moved_data <- lapply(as.list(move_names), function(x)
{
df <- df |>
relocate(!!!syms(paste0(x, "_", 2:3)),
.after = all_of(x))
}
)
它分别移动 x 和 y,但它创建了单独的列表,但我只想拥有带有重定位列的原始 df。
更新:
我应该清楚我的真实数据框有大约 500 列,其中到处都是要移动的列。因此,提供所需列名顺序的完整向量是不可行的。
我拥有的是:我有原始列的名称,即 x 和 y,我有要移动的列的名称,即 x_2、x_3 , y_2, y_3.
不确定这是否是您想要的。
具有列名顺序的向量
假设您有一个包含列顺序的向量 relocate_name
:
library(tidyverse)
relocate_name <- c("a", "x", "x_2", "x_3", "b", "y", "y_2", "y_3", "c")
df %>% relocate(any_of(relocate_name))
带有列名前缀的向量
或者如果你只有订单的前缀,我们就称它为relocate_name2
:
relocate_name2 <- c("a", "x", "b", "y", "c")
df %>% relocate(starts_with(relocate_name2))
将 x 和 y 组合在一起
或者如果您只想将 x
和 y
“组合”在一起:
df %>%
relocate(starts_with("x"), .after = "x") %>%
relocate(starts_with("y"), .after = "y")
输出
以上输出都是一样的
a x x_2 x_3 b y y_2 y_3 c
1 1 1 1 5 1 3 3 1 1
2 2 2 2 6 2 4 4 2 2
library(rlist)
# split based in colname-part before _
L <- split.default(df, f = gsub("(.*)_.*", "\1", names(df)))
# remove names with an underscore
# this is the new order, it should match the names of list L !!
neworder <- names(df)[!grepl("_", names(df))]
# [1] "a" "x" "b" "y" "c"
# cbind list elements together
ans <- rlist::list.cbind(L[neworder])
# a x.x x.x_2 x.x_3 b y.y y.y_2 y.y_3 c
# 1 1 1 1 5 1 3 3 1 1
# 2 2 2 2 6 2 4 4 2 2
# create tidy names again
names(ans) <- gsub(".*\.(.*)", "\1", names(ans))
# a x x_2 x_3 b y y_2 y_3 c
# 1 1 1 1 5 1 3 3 1 1
# 2 2 2 2 6 2 4 4 2 2
在基数 R 中:
df[match(c('a', 'x', 'x_2', 'x_3', 'b', 'y', 'y_2', 'y_3', 'c'), names(df))]
#> a x x_2 x_3 b y y_2 y_3 c
#> 1 1 1 1 5 1 3 3 1 1
#> 2 2 2 2 6 2 4 4 2 2
好吧,这可能是有史以来最糟糕的解决方法,我真的不明白我到底在做什么(尤其是 <<-
),但它确实有效。
在你们这里的帮助下更多地意识到问题后,我的一般想法是“循环”我的 x 和 y 名称,从列名称向量中删除这些新的 _2 和 _3 列,然后re-append 他们在他们的“基础”x 和 y 列之后。
search_names <- c("x", "y")
df_names <- names(df)
new_names <- lapply(search_names, function(x)
{
start <- which(df_names == x)
without_new_names <- setdiff(df_names, paste0(x, "_", 2:3))
df_names <<- append(without_new_names, values = paste0(x, "_", 2:3), after = start)
})[[length(search_names)]]
df |>
relocate(any_of(new_names))
a x x_2 x_3 b y y_2 y_3 c
1 1 1 1 5 1 3 3 1 1
2 2 2 2 6 2 4 4 2 2