![](/img/trans.png)
[英]How to combine the across () function with mutate () and case_when () to mutate values in multiple columns according to a condition?
[英]R - How can I combine values across multiple columns in a pairwise matching fashion, possibly using 'mutate' or 'coalesce'?
我有一個來自大型調查的數據集,其中包含約 2k 個參與者(行)和大約 160 個變量(列)。 相關欄目包括:
cl.exp "yes" 和 "no" 的問題是同義詞,除了 no.Q6 和 no.Q7 是 yes.Q6 和 yes.Q7 的倒數; 即,no.Q7 與 yes.Q6 同義,no.Q6 與 yes.Q7 同義。
前幾行可能如下所示:
ID | cl.exp | cl.yes.Q1 | cl.yes.Q2 | cl.yes.Q3 | cl.yes.Q4 | cl.yes.Q5 | cl.yes.Q6 | cl.yes.Q7 | 分類號Q1 | 分類號Q2 | 分類號Q3 | 分類號Q4 | 分類號Q5 | 分類號Q6 | 分類號Q7 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
1 | 不 | 不適用 | 不適用 | 不適用 | 不適用 | 不適用 | 不適用 | 不適用 | 2 | 6 | 3 | 4 | 3 | 7 | 4 |
2 | 不 | 不適用 | 不適用 | 不適用 | 不適用 | 不適用 | 不適用 | 不適用 | 3 | 6 | 6 | 6 | 5 | 7 | 3 |
3 | 是的 | 2 | 5 | 6 | 6 | 4 | 2 | 7 | 不適用 | 不適用 | 不適用 | 不適用 | 不適用 | 不適用 | 不適用 |
4 | 是的 | 7 | 1 | 5 | 6 | 7 | 2 | 5 | 不適用 | 不適用 | 不適用 | 不適用 | 不適用 | 不適用 | 不適用 |
您會注意到參與者在 cl.yes.Q1-7 或 cl.no.Q1-7 中都有值,但從不會兩者都有。 我想執行以下任一操作:a) 將 cl.no.Q1-7 中的值移動到 cl.yes.Q1-7 的相應列中,或 b) 創建新列,將適當的列從cl.yes 和 cl.no,即 cl.yes.Q1 和 cl.no.Q1,cl.yes.Q2 和 cl.no.Q2,以此類推。
我使用以下代碼解決了 no.Q6 和 no.Q7 反向問題:
df[15:16] <- df[16:15]
然后我執行以下操作:
df.yes <- df %>%
select(contains("cl.yes"), id, cl.exp) %>%
drop_na()
df.no <- df %>%
select(contains("cl.no"), id, cl.exp) %>%
drop_na()
names(df.yes) <- gsub("cl.yes.", "cl.", names(df.yes))
names(df.no) <- gsub("cl.no.", "cl.", names(df.no))
df.cl <- merge(df.yes, df.no, all = TRUE)
這給了我一個包含合並列的新數據框。 但是,我相信一定有比這更簡單/更干凈/更優雅的解決方案,特別是能夠將數據保存在原始數據框中。 我嘗試了一些 mutate 和 coalesce 的迭代,但永遠不會成功。 如果有人有一兩行代碼基本上和我在這里做的事情一樣,我將非常感謝你的洞察力。 謝謝!
此解決方案使用 for 循環動態coalesce
以相同問題編號結尾的列。 您需要知道最后一個問題編號才能記下 for 循環的迭代器。
library(dplyr)
dat2 <- dat %>% select(ID, cl.exp)
for (i in 1:7){
temp <- dat %>%
select(ends_with(paste0("Q", i))) %>%
as.list()
dat2[[paste0("cl.Q", i)]] <- coalesce(!!!temp)
}
dat2
# ID cl.exp cl.Q1 cl.Q2 cl.Q3 cl.Q4 cl.Q5 cl.Q6 cl.Q7
# 1 1 No 2 6 3 4 3 7 4
# 2 2 No 3 6 6 6 5 7 3
# 3 3 Yes 2 5 6 6 4 2 7
# 4 4 Yes 7 1 5 6 7 2 5
注意:我沒有交換 Q6 和 Q7,但我相信您已經找到了最好的方法。
數據
dat <- read.table(text = "ID cl.exp cl.yes.Q1 cl.yes.Q2 cl.yes.Q3 cl.yes.Q4 cl.yes.Q5 cl.yes.Q6 cl.yes.Q7 cl.no.Q1 cl.no.Q2 cl.no.Q3 cl.no.Q4 cl.no.Q5 cl.no.Q6 cl.no.Q7
1 No NA NA NA NA NA NA NA 2 6 3 4 3 7 4
2 No NA NA NA NA NA NA NA 3 6 6 6 5 7 3
3 Yes 2 5 6 6 4 2 7 NA NA NA NA NA NA NA
4 Yes 7 1 5 6 7 2 5 NA NA NA NA NA NA NA",
header = TRUE)
像這樣的東西怎么樣:
library(tidyverse)
dat <- tibble::tribble(~ID, ~cl.exp, ~cl.yes.Q1, ~cl.yes.Q2, ~cl.yes.Q3, ~cl.yes.Q4, ~cl.yes.Q5, ~cl.yes.Q6, ~cl.yes.Q7, ~cl.no.Q1, ~cl.no.Q2, ~cl.no.Q3, ~cl.no.Q4, ~cl.no.Q5, ~cl.no.Q6, ~cl.no.Q7,
1, "No",NA,NA,NA,NA,NA,NA,NA,2,6,3,4,3,7,4,
2, "Yes",3,6,6,6,5,7,3, NA,NA,NA,NA,NA,NA,NA)
bind_cols(dat %>% select(c(ID, cl.exp)),
coalesce(dat %>%
select(contains("no")) %>%
setNames(gsub("\\.no", "", names(.))),
dat %>%
select(contains("yes"))%>%
setNames(gsub("\\.yes", "", names(.)))))
#> # A tibble: 2 × 9
#> ID cl.exp cl.Q1 cl.Q2 cl.Q3 cl.Q4 cl.Q5 cl.Q6 cl.Q7
#> <dbl> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1 1 No 2 6 3 4 3 7 4
#> 2 2 Yes 3 6 6 6 5 7 3
由reprex 包於 2022-06-10 創建 (v2.0.1)
我想你需要這個:
library(dplyr)
library(tidyr)
df %>%
pivot_longer(cols = -c(ID, cl.exp),
names_to = c('.value', 'name'),
names_pattern = '(.*)(\\d+)') %>%
mutate(cl.yes.Q = coalesce(cl.yes.Q, cl.no.Q), .keep="unused") %>%
pivot_wider(names_from = name, values_from = cl.yes.Q)
ID cl.exp `1` `2` `3` `4` `5` `6` `7`
<int> <chr> <int> <int> <int> <int> <int> <int> <int>
1 1 No 2 6 3 4 3 7 4
2 2 No 3 6 6 6 5 7 3
3 3 Yes 2 5 6 6 4 2 7
4 4 Yes 7 1 5 6 7 2 5
您應該能夠像這樣使用mutate
和coalesce
(在交換no.Q6
和no.Q7
之后,如上所述):
library(dplyr)
result <- df %>% mutate(cl.Q1 = coalesce(cl.yes.Q1, cl.no.Q1),
cl.Q2 = coalesce(cl.yes.Q2, cl.no.Q2),
cl.Q3 = coalesce(cl.yes.Q3, cl.no.Q3),
cl.Q4 = coalesce(cl.yes.Q4, cl.no.Q4),
cl.Q5 = coalesce(cl.yes.Q5, cl.no.Q5),
cl.Q6 = coalesce(cl.yes.Q6, cl.no.Q6),
cl.Q7 = coalesce(cl.yes.Q7, cl.no.Q7)) %>%
select(-(cl.yes.Q1:cl.no.Q7))
我們只需使用mutate
來創建cl.Q*
* 列,分別合並來自cl.yes.Q*
和cl.no.Q*
列的值。 然后,我們使用select
刪除原始的cl.yes.Q*
和cl.no.Q*
列。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.