我有以下資料框:
A1_Q1 <- c(1, 2, 3)
A1_Q2 <- c(4, 5, 6)
A1_Q3 <- c(7, 8, 9)
A1_Q4 <- c(10, 11, 12)
A1_Q5 <- c(13, 14, 15)
A1_Q6 <- c(16, 17, 18)
A2_Q1 <- c(1, 2, 3)
A2_Q2 <- c(4, 5, 6)
A2_Q3 <- c(7, 8, 9)
A2_Q4 <- c(10, 11, 12)
A2_Q5 <- c(13, 14, 15)
A2_Q6 <- c(16, 17, 18)
df <- data.frame(A1_Q1, A1_Q2, A1_Q3, A1_Q4, A1_Q5, A1_Q6,
A2_Q1, A2_Q2, A2_Q3, A2_Q4, A2_Q5, A2_Q6)
我想創建名為col1a, col1b, col1c.
df <- df %>%
unite("col1a",
A1_Q1,
A1_Q2,
sep="-",
remove = FALSE) %>%
unite("col1b",
A1_Q3,
A1_Q4,
sep="-",
remove = FALSE) %>%
unite("col1c",
A1_Q5,
A1_Q6,
sep="-",
remove = FALSE)
我也想對 A2 變數做同樣的事情。
有什么方法可以col2a, col2b, col2c一次性創建呼叫的變數嗎?我正在設想一個看起來像這樣的 for 回圈:
for (i in 1:2) {
df <- df %>%
unite("colia",
Ai_Q1,
Ai_Q2,
sep="-",
remove = FALSE) %>%
unite("colib",
Ai_Q3,
Ai_Q4,
sep="-",
remove = FALSE) %>%
unite("colic",
Ai_Q5,
Ai_Q6,
sep="-",
remove = FALSE)
}
uj5u.com熱心網友回復:
我們可以使用正則運算式^A1和^A2列子grep集sb;要創建它,我們回圈使用lapply數字1:2并使用sprintf(優點是,不會混淆列是安全的A1,A2我們可以稍后將數字用于新列名)。在第二步中,我們基本上paste0將各自的兩列放在一起,例如sb[(1:2) x]前兩sb列放在一起,然后遞增2直到ncol(sb)達到。在迭代結束時,我們將paste0 colnumberx和lettersconstant 的相應元素轉換為字串setNames。最后,我們簡單地cbind將結果串列添加到資料框中。
res <- lapply(1:2, \(x) {
sb <- df[grep(sprintf('^A%s', x), names(df))]
lapply((0:((ncol(sb) - 1)/2))*2, \(x) Reduce(\(y, z) paste0(y, '-', z), sb[(1:2) x])) |>
setNames(paste0('col', x, letters[seq_len((ncol(sb))/2)]))
}) |> cbind(df)
res
# col1a col1b col1c col2a col2b col2c A1_Q1 A1_Q2 A1_Q3 A1_Q4 A1_Q5 A1_Q6 A2_Q1
# 1 1-4 7-10 13-16 1-4 7-10 13-16 1 4 7 10 13 16 1
# 2 2-5 8-11 14-17 2-5 8-11 14-17 2 5 8 11 14 17 2
# 3 3-6 9-12 15-18 3-6 9-12 15-18 3 6 9 12 15 18 3
# A2_Q2 A2_Q3 A2_Q4 A2_Q5 A2_Q6
# 1 4 7 10 13 16
# 2 5 8 11 14 17
# 3 6 9 12 15 18
請注意,這可能需要一個預處理步驟,如果它們沒有像您的示例中所示A*那樣很好地排序。Q
更新
對于舊的 R 版本,使用此代碼(但最好始終使用更新的軟體)。
res <- cbind(lapply(1:2, function(x) {
sb <- df[grep(sprintf('^A%s', x), names(df))]
lapply((0:((ncol(sb) - 1)/2))*2, function(x) Reduce(function(y, z) paste0(y, '-', z), sb[(1:2) x])) |>
setNames(paste0('col', x, letters[seq_len((ncol(sb))/2)]))
}), df)
uj5u.com熱心網友回復:
這是另一個解決方案:
- 使用
paste0and[[訪問 cols 而無需對索引進行硬編碼。 - 用于
map_dfc迭代,.x作為索引并使用新的 cols 獲取 data.frame。 map_dfc從內部呼叫mutate以將新列自動系結到 data.frame。
library(tidyverse)
A1_Q1 <- c(1, 2, 3)
A1_Q2 <- c(4, 5, 6)
A1_Q3 <- c(7, 8, 9)
A1_Q4 <- c(10, 11, 12)
A1_Q5 <- c(13, 14, 15)
A1_Q6 <- c(16, 17, 18)
A2_Q1 <- c(1, 2, 3)
A2_Q2 <- c(4, 5, 6)
A2_Q3 <- c(7, 8, 9)
A2_Q4 <- c(10, 11, 12)
A2_Q5 <- c(13, 14, 15)
A2_Q6 <- c(16, 17, 18)
df <- data.frame(A1_Q1, A1_Q2, A1_Q3, A1_Q4, A1_Q5, A1_Q6,
A2_Q1, A2_Q2, A2_Q3, A2_Q4, A2_Q5, A2_Q6)
df %>%
mutate(
map_dfc(
1:2,
~ {
cols <- list(
paste(
df[[paste0("A", .x, "_Q1")]],
df[[paste0("A", .x, "_Q2")]],
sep = "-"
),
paste(
df[[paste0("A", .x, "_Q3")]],
df[[paste0("A", .x, "_Q4")]],
sep = "-"
),
paste(
df[[paste0("A", .x, "_Q5")]],
df[[paste0("A", .x, "_Q6")]],
sep = "-"
)
)
names(cols) <- c(
paste0("col", .x, "a"),
paste0("col", .x, "b"),
paste0("col", .x, "c")
)
cols
}
)
)
uj5u.com熱心網友回復:
從列名稱的子字串中創建輸出列 ('nm1') 的名稱,通過使用創建的索引將資料拆分list為連續的列對,回圈遍歷with和按行排列的列with和將輸出分配給資料中的新列split.defaultgllistlapplypastelistdo.calllist
nm1 <- paste0("col", rep(unique( sub(".(\\d )_.*", "\\1",
names(df))), each = 3), letters[1:3])
df[nm1] <- lapply(split.default(df, as.integer(gl(ncol(df), 2, ncol(df)))),
function(x) do.call(paste, c(x, sep = '-')))
-輸出
> df
A1_Q1 A1_Q2 A1_Q3 A1_Q4 A1_Q5 A1_Q6 A2_Q1 A2_Q2 A2_Q3 A2_Q4 A2_Q5 A2_Q6 col1a col1b col1c col2a col2b col2c
1 1 4 7 10 13 16 1 4 7 10 13 16 1-4 7-10 13-16 1-4 7-10 13-16
2 2 5 8 11 14 17 2 5 8 11 14 17 2-5 8-11 14-17 2-5 8-11 14-17
3 3 6 9 12 15 18 3 6 9 12 15 18 3-6 9-12 15-18 3-6 9-12 15-18
中的一個選項tidyverse是使用 重塑為“長”格式pivot_longer,使用 將名稱列分成兩部分,使用separate,從 Q 值創建“a”、“b”、“c”值case_when,unite列,使用 重塑回寬格式pivot_wider并與原始資料系結
library(dplyr)
library(tidyr)
library(stringr)
df %>%
mutate(rn = row_number()) %>%
pivot_longer(cols = -rn) %>%
separate(name, into = c("name1", "name2")) %>%
mutate( name2 = case_when(name2 %in% c("Q1", "Q2") ~ "a",
name2 %in% c("Q3", "Q4") ~ "b", TRUE ~ "c")) %>%
group_by(rn, name1, name2) %>%
summarise(value = str_c(value, collapse = '-'), .groups = 'drop') %>%
mutate(name1 = str_replace(name1, "\\D ", "col")) %>%
unite(name, name1, name2, sep = "") %>%
pivot_wider(names_from = name, values_from = value) %>%
select(-rn) %>%
bind_cols(df, .)
-輸出
A1_Q1 A1_Q2 A1_Q3 A1_Q4 A1_Q5 A1_Q6 A2_Q1 A2_Q2 A2_Q3 A2_Q4 A2_Q5 A2_Q6 col1a col1b col1c col2a col2b col2c
1 1 4 7 10 13 16 1 4 7 10 13 16 1-4 7-10 13-16 1-4 7-10 13-16
2 2 5 8 11 14 17 2 5 8 11 14 17 2-5 8-11 14-17 2-5 8-11 14-17
3 3 6 9 12 15 18 3 6 9 12 15 18 3-6 9-12 15-18 3-6 9-12 15-18
或者另一個更簡單的選擇是使用回圈邏輯向量對交替列進行子集化,使用回圈遍歷相應的列Map,paste然后分配回去以創建新列
df[nm1] <- Map(function(x, y) paste(x, y, sep = "-"), df[c(TRUE, FALSE)],
df[c(FALSE, TRUE)])
-輸出
> df
A1_Q1 A1_Q2 A1_Q3 A1_Q4 A1_Q5 A1_Q6 A2_Q1 A2_Q2 A2_Q3 A2_Q4 A2_Q5 A2_Q6 col1a col1b col1c col2a col2b col2c
1 1 4 7 10 13 16 1 4 7 10 13 16 1-4 7-10 13-16 1-4 7-10 13-16
2 2 5 8 11 14 17 2 5 8 11 14 17 2-5 8-11 14-17 2-5 8-11 14-17
3 3 6 9 12 15 18 3 6 9 12 15 18 3-6 9-12 15-18 3-6 9-12 15-18
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/537545.html
標籤:r循环
下一篇:在回圈中擺脫子圖中不需要的面板圖
