簡體   English   中英

當函數采用不同列的多個參數時使用 dplyr mutate_at

[英]Using dplyr mutate_at when a function takes multiple arguments which are different columns

我有一個包含大量列的data.frame ,其名稱遵循某種模式。 比如:

df <- data.frame(
  x_1 = c(1, NA, 3), 
  x_2 = c(1, 2, 4), 
  y_1 = c(NA, 2, 1), 
  y_2 = c(5, 6, 7)
)

我想應用mutate_at對每對列執行相同的操作。 如:

df %>%
  mutate(
    x = ifelse(is.na(x_1), x_2, x_1), 
    y = ifelse(is.na(y_1), y_2, y_1)
  )

有沒有辦法用mutate_at / mutate_each做到這mutate_each

這個:

df %>%
  mutate_each(vars(x_1, y_1), funs(ifelse(is.na(.), vars(x_2, y_2), .)))

我嘗試過的各種變體都失敗了。

該問題類似於在 dplyr mutate_at 調用中使用多列的函數,但不同之處在於函數調用的第二個參數不是單個列,而是 vars 中每一列的不同列。

提前致謝。

我不知道你是否可以這樣理解,但這里有一個不同的角度來看待這個問題。 如果您發現自己擁有非常廣泛的數據(例如,大量具有相似名稱的列)並且您想對它們做一些事情,那么使用tidyr::gather tidy數據(在stata很長)可能會有所幫助(請參閱此處的文檔http ://tidyr.tidyverse.org/ )。

> df %>% gather()
   key value
1  x_1     1
2  x_1    NA
3  x_1     3
4  x_2     1
5  x_2     2
6  x_2     4
7  y_1    NA
8  y_1     2
9  y_1     1
10 y_2     5
11 y_2     6
12 y_2     7

將數據轉換為這種格式后,使用group_by來組合和重新排列值比嘗試mutate_at更容易。 例如,您可以使用df %>% gather() %>% mutate(var = substr(key,1,1))獲取第一個值,並使用group_by(var)以不同方式操作x s 和y s。

老問題,但我同意 Jesse 的觀點,您需要稍微整理一下數據。 gather將是要走的路,但不知何故缺乏stats::reshape的可能性,您可以在其中指定要收集的列組。 所以這是一個帶有reshape的解決方案:

df %>% 
   reshape(varying   = list(c("x_1", "y_1"), c("x_2", "y_2")), 
           times     = c("x", "y"),
           direction = "long") %>% 
   mutate(x = ifelse(is.na(x_1), x_2, x_1)) %>% 
   reshape(idvar     = "id", 
           timevar   = "time",
           direction = "wide") %>% 
   rename_all(funs(gsub("[a-zA-Z]+(_*)([0-9]*)\\.([a-zA-Z]+)", "\\3\\1\\2", .)))
#   id x_1 x_2 x y_1 y_2 y
# 1  1   1   1 1  NA   5 5
# 2  2  NA   2 2   2   6 2
# 3  3   3   4 3   1   7 1

為了使用任意數量的列對執行此操作,您可以執行以下操作:

df2 <- setNames(cbind(df, df), c(t(outer(letters[23:26], 1:2, paste, sep = "_"))))
v <- split(names(df2), purrr::map_chr(names(df2), ~ gsub(".*_(.*)", "\\1", .)))
n <- unique(purrr::map_chr(names(df2), ~ gsub("_[0-9]+", "", .) ))
df2 %>% 
    reshape(varying   = v, 
            times     = n,
            direction = "long") %>% 
     mutate(x = ifelse(is.na(!!sym(v[[1]][1])), !!sym(v[[2]][1]), !!sym(v[[1]][1]))) %>% 
     reshape(idvar     = "id", 
             timevar   = "time",
             direction = "wide") %>% 
     rename_all(funs(gsub("[a-zA-Z]+(_*)([0-9]*)\\.([a-zA-Z]+)", "\\3\\1\\2", .)))
#   id w_1 w_2 w x_1 x_2 x y_1 y_2 y z_1 z_2 z
# 1  1   1   1 1  NA   5 5   1   1 1  NA   5 5
# 2  2  NA   2 2   2   6 2  NA   2 2   2   6 2
# 3  3   3   4 3   1   7 1   3   4 3   1   7 1

這假設應該比較的列彼此相鄰,並且具有可能的 NA 值的所有列都在以_1為后綴的列中,並且替換值列以_2為后綴。

當我問這個問題時,答案是“你不能!” 這不再是答案,因為tidyr現在支持pivot_widerpivot_longer

暫無
暫無

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

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