簡體   English   中英

基於謂詞函數(dplyr :: mutate_if)變換數據框的列

[英]Mutating columns of a data frame based on a predicate function (dplyr::mutate_if)

我想使用dplyr的mutate_if()函數將list-columns轉換為data-frame-columns,但是當我嘗試這樣做時遇到一個令人費解的錯誤。 我使用的是dplyr 0.5.0,purrr 0.2.2,R 3.3.0。

基本設置如下所示:我有一個數據框d ,其中一些列是列表:

d <- dplyr::data_frame(
  A = list(
    list(list(x = "a", y = 1), list(x = "b", y = 2)),
    list(list(x = "c", y = 3), list(x = "d", y = 4))
  ),
  B = LETTERS[1:2]
)

我想使用以下函數將列的列(在本例中為d$A )轉換為數據幀列:

tblfy <- function(x) {
  x %>%
    purrr::transpose() %>%
    purrr::simplify_all() %>%
    dplyr::as_data_frame()
}

也就是說,我希望列表列d$A被列表lapply(d$A, tblfy) ,這是

[[1]]
#  A tibble: 2 x 2
      x     y
  <chr> <dbl>
1     a     1
2     b     2

[[2]]
# A tibble: 2 x 2
      x     y
  <chr> <dbl>
1     c     3
2     d     4

當然,在這個簡單的例子中,我可以做一個簡單的重新分配。 然而,重點是我想以編程方式,理想情況下使用dplyr,以一種通用的方式處理任意數量的列表列。

這是我絆倒的地方:當我嘗試使用以下應用程序將list-columns轉換為data-frame-columns時

d %>% dplyr::mutate_if(is.list, funs(tblfy))

我收到一條錯誤消息,我不知道如何解釋:

Error: Each variable must be named.
Problem variables: 1, 2

為什么mutate_if()會失敗? 如何正確應用它以獲得所需的結果?

備注

一位評論者指出函數tblfy()應該是矢量化的。 這是一個合理的建議。 但是 - 除非我的矢量化不正確 - 這似乎並沒有找到問題的根源。 插入tblfy()的矢量化版本,

tblfy_vec <- Vectorize(tblfy)

進入mutate_if()失敗並出現錯誤

Error: wrong result size (4), expected 2 or 1

更新

在獲得purrr的一些經驗之后,我現在發現以下方法是自然的,如果有點啰嗦:

d %>%
  map_if(is.list, ~ map(., ~ map_df(., identity))) %>%
  as_data_frame()

這與@ alistaire的解決方案或多或少完全相同,但是使用map_if() ,resp。 map() ,代替mutate_if() ,resp。 Vectorize()

沒有任何復制的就地轉換:

library(data.table)

for (col in d) if (is.list(col)) lapply(col, setDF)

d
#Source: local data frame [2 x 2]
#
#                A B
#1 <S3:data.frame> A
#2 <S3:data.frame> B

原來的tblfy函數錯誤輸出(即使它的元素是直接鏈接的),所以讓我們重新rowwise()一下,添加向量化,這樣我們就可以避免在其他方面必要的先前rowwise()調用:

tblfy <- Vectorize(function(x){x %>% purrr::map_df(identity) %>% list()})

現在我們可以很好地使用mutate_if

d %>% mutate_if(purrr::is_list, tblfy)
## Source: local data frame [2 x 2]
## 
##                A     B
##           <list> <chr>
## 1 <tbl_df [2,2]>     A
## 2 <tbl_df [2,2]>     B

......如果我們不知道那里有什么,

d %>% mutate_if(purrr::is_list, tblfy) %>% tidyr::unnest()
## Source: local data frame [4 x 3]
## 
##       B     x     y
##   <chr> <chr> <dbl>
## 1     A     a     1
## 2     A     b     2
## 3     B     c     3
## 4     B     d     4

幾個筆記:

  • map_df(identity)似乎比任何替代配方更有效地構建map_df(identity) 我知道identity調用似乎是不必要的,但大多數其他一切都會破壞。
  • 我不確定tblfy會有多廣泛用處,因為它在某種程度上取決於列表列中列表的結構,這可能會有很大差異。 如果你有很多類似的結構,我認為它很有用。
  • 可能有一種方法可以用pmap而不是Vectorize來做到這一點,但我不能讓它與一些粗略的嘗試一起工作。

暫無
暫無

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

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