mutate_if,summary_at等将data.table强制转换为data.frame

时间:2019-05-15 08:48:23

标签: r dplyr data.table tibble

似乎有些dplyr函数,包括mutate_if,mutate_all,mutate_at等将data.table输入强制到data.frame。即使在?mutate_all中进行了记录,这也似乎是一种奇怪的行为(在“值”下,它表示为“ data.frame”-但不会强迫小标题显示为data.frames。)

require(dplyr)
require(data.table)
data("iris")
dt <- as.data.table(iris)
class(dt)

[1]“数据表”“数据框架”

class(mutate_if(dt, is.numeric, as.numeric))

[1]“数据框架”

但是,这种动作不会发生:

tb <- as_tibble(iris)
class(tb)

[1]“ tbl_df”“ tbl”“ data.frame”

class(mutate_if(tb, is.numeric, as.numeric))

[1]“ tbl_df”“ tbl”“ data.frame”

是否有某种方法可以维护data.table,或者每次使用范围限定的mutate函数之一时都需要强制as.data.table吗?

3 个答案:

答案 0 :(得分:1)

您的问题可能没有令人满意的答案,但是这些包装函数可以使您不必每次都转换回数据表。

如果您不想将它们包含在每个脚本或项目中,又不想将它们放入.Rprofile中,则甚至可以用它们制作一个小小的包装。非常简单。

mutate_all <- function(.tbl, ...) {
  if ("data.table" %in% class(.tbl)) {
    .tbl %>% mutate_all(...) %>% as.data.table()
  } else {
    .tbl %>% mutate_all(...)
  }
}
mutate_if <- function(.tbl, ...) {
  if ("data.table" %in% class(.tbl)) {
    .tbl %>% mutate_if(...) %>% as.data.table()
  } else {
    .tbl %>% mutate_if(...)
  }
}
mutate_at <- function(.tbl, ...) {
  if ("data.table" %in% class(.tbl)) {
    .tbl %>% mutate_at(...) %>% as.data.table()
  } else {
    .tbl %>% mutate_at(...)
  }
}
transmute_all <- function(.tbl, ...) {
  if ("data.table" %in% class(.tbl)) {
    .tbl %>% transmute_all(...) %>% as.data.table()
  } else {
    .tbl %>% transmute_all(...)
  }
}
transmute_if <- function(.tbl, ...) {
  if ("data.table" %in% class(.tbl)) {
    .tbl %>% transmute_if(...) %>% as.data.table()
  } else {
    .tbl %>% transmute_if(...)
  }
}
transmute_at <- function(.tbl, ...) {
  if ("data.table" %in% class(.tbl)) {
    .tbl %>% transmute_at(...) %>% as.data.table()
  } else {
    .tbl %>% transmute_at(...)
  }
}

答案 1 :(得分:1)

如果您想尝试其他方法, 我最近发布了table.express软件包, 它使用许多dplyr和自定义动词来构建data.table表达式。

现在table.express v0.2.0已经发布, 可以将更多dplyr动词映射到自定义动词, 但有一些警告(请检查链接的插图)。 一些例子:

library(data.table)
library(table.express)

data("iris")
DT <- as.data.table(iris)

# mutate_all (modification by reference does not print)
DT %>%
  start_expr %>%
  mutate_sd(everything(), as.integer) %>%
  end_expr

# mutate_if
DT %>%
  start_expr %>%
  mutate_sd(is.numeric(.COL), as.integer) %>%
  end_expr

# mutate_at
DT %>%
  start_expr %>%
  mutate_sd(contains("."), .COL * 1.5) %>%
  end_expr

# transmute_all
DT %>%
  start_expr %>%
  transmute_sd(everything(), as.integer) %>%
  end_expr

# transmute_if
DT %>%
  start_expr %>%
  transmute_sd(is.numeric(.COL), as.integer) %>%
  end_expr

# transmute_at
DT %>%
  start_expr %>%
  transmute_sd(contains("."), as.integer) %>%
  end_expr

请注意,mutate_sd默认通过引用进行修改, 因此请根据需要在示例之间重新定义DT

答案 2 :(得分:0)

您尝试过使用

df %>%
mutate_if(yourmutate) %>%
data.table()

您的框架将同时为data.tabledata.frame

按照您的示例:

require(dplyr)
require(data.table)
data("iris")
dt <- as.data.table(iris)
class(dt)
#
dt <- mutate_if(dt, is.numeric, as.numeric) %>% data.table()
class(dt)