簡體   English   中英

跨列 case_when 變異以創建新的“標志”列

[英]Mutate across columns case_when to make a new "Flag" column

我有一個巨大的數據集 (df),其中包含許多列,列出了每個國家 (ISO3) 和每年 (Year) 接受治療的人數 x (例如 Treat_1) 的信息。

我需要生成一個名為“Flag_Treat_X”的新列(其中 X 代表原始列名,例如 Treat_1)。 在本專欄中,我需要將與上一年相比的任何治療下降記錄為“下降”,增加為“上升”,在缺失數據的情況下記錄為 NA。 所有包含治療信息的列的名稱中都有“_”,但實際的 df 使用復雜的名稱,如 HIV_treatment 等,而不是此處使用的字符串和數字的組合。 我知道有幾種方法可以逐列(見下文),但數據集非常龐大,變量名稱經常變化,我需要一種自動化的方法來做到這一點。

這是一個簡化示例的代碼:

ISO3 <- c("AFG", "AFG","AFG", "BEN", "BEN","BEN", "GIN", "GIN", "GIN", "ZWE", "ZWE", "ZWE")
Year <- c(2020, 2021, 2022, 2020, 2021, 2022, 2020, 2021, 2022, 2020, 2021, 2022)
Treat_1 <- c(100, 110, 120, 300, 330, 360, 200, 220, 100, 300, NA, 320)

df = data.frame(ISO3, Year, Treat_1)

這是我如何逐列手動完成的示例

df_poutcome %>%
   group_by(ISO3) %>%
   mutate(Target_art_n_pf = case_when(Treat_1<lag(Treat_1) ~ "down",
                                      Treat_1>lag(Treat_1) ~ "up", 
                                      TRUE ~ as.character(NA)))

這是一個使用循環“幾乎”工作的示例(不是很優雅)

for (i in grep("_", names(temp), value=TRUE)){
 
  varname = ((gsub(" ", "", paste("Flag_",i))))
  temp = temp %>%
       group_by(ISO3) %>%
       mutate(!!varname:= case_when(i<lag(i) ~ "down",
                                   i>lag(i) ~ "up"))

}

錯誤是我只獲得所有新“Flag_ [...]”變量和代碼的 NA 值

TRUE ~ as.character(NA)

不在 case_when 代碼中運行,因此我必須將其刪除。

期望的結果應如下所示:

ISO3 款待_1 Flag_Treat_1
AFG 2020 100 不適用
AFG 2021 110 向上
AFG 2022 120 向上
2020 300 不適用
2021 330 向上
2022 360 向上
杜松子酒 2020 200 不適用
杜松子酒 2021 220 向上
杜松子酒 2022 100
ZWE 2020 300 不適用
ZWE 2021 不適用 不適用
ZWE 2022 320 不適用

作為獎勵,任何人都知道,自動為每種處理生成國家特定的圖以進行目視檢查會很棒。 這不那么緊急。 到目前為止,我有:

countries <- unique(df$ISO3)

plot_list <- list()
i <- 1

for (c in countries){
  pl <- ggplot(data = df %>% filter(ISO3 == c)) +
    geom_point(aes(Year, Treat_1), size = 3, color = 'red') +
    labs(title = as.character(c), x = 'wave', y = 'value') +
    theme_bw(base_size = 16) +
    xlim(2020,  2022)
  
  plot_list[[i]] <- pl
  i <- i + 1
}

pdf('path/filename.pdf')
pdf.options(width = 9, height = 7)
for (i in 1:length(plot_list)){
  print(plot_list[[i]])
}
dev.off()

這是針對一個治療變量 Treat_1 並且以自動方式對所有治療變量執行此操作會很棒

提前感謝您的幫助。

您可以使用 cross across()跨具有條件的列(此處為名稱中包含"_"的列)應用 function,並使用.names參數命名結果列:

df %>%
  group_by(ISO3) %>%
  mutate(across(contains("_"),
    \(x) case_when(
      x < lag(x) ~ "down",
      x > lag(x) ~ "up", 
      TRUE ~ as.character(NA)
    ),
    .names = "flag_{.col}"
  ))
# # A tibble: 12 × 4
# # Groups:   ISO3 [4]
#    ISO3   Year Treat_1 flag_Treat_1
#    <chr> <dbl>   <dbl> <chr>       
#  1 AFG    2020     100 NA          
#  2 AFG    2021     110 up          
#  3 AFG    2022     120 up          
#  4 BEN    2020     300 NA          
#  5 BEN    2021     330 up          
#  6 BEN    2022     360 up          
#  7 GIN    2020     200 NA          
#  8 GIN    2021     220 up          
#  9 GIN    2022     100 down        
# 10 ZWE    2020     300 NA          
# 11 ZWE    2021      NA NA          
# 12 ZWE    2022     320 NA    

非常感謝大家的快速回復。 我最終使用了混合的響應來讓它在我身邊運行。 代碼如下。


df %>%
  group_by(ISO3) %>%
  mutate(across(contains("_"),
                ~case_when(
                  .x < lag(.x) ~ "down",
                  .x > lag(.x) ~ "up", 
                  TRUE ~ as.character(NA)
                ),
                .names = "flag_{.col}"
  ))

我不得不將 Gregor Thomas 建議的\(x)更改為 jdobres ~case_when(.x < lag(.x) ~ "down", .x > lag(.x) ~ "up", TRUE ~ as.character(NA) )因為它給了我一個意想不到的符號

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM