【问题标题】:map() to iterate over columns of dataframemap() 遍历数据框的列
【发布时间】:2020-12-16 11:32:44
【问题描述】:

我想使用 purrr 包中的 map() 来迭代我的数据框的变量子集。有没有标准和方便的方法? 采取以下示例数据集:

library(data.table)
library(purrr)
dt <- data.table(id= c("Alpha 1","Alpha 2","Alpha 3","Beta 1"),
id2= c("gamma 1","gamma 2","gamma 3","Delta 1") ,
y = rnorm(4))
        id     id2          y
1: Alpha 1 gamma 1 -1.1184009
2: Alpha 2 gamma 2  0.4347047
3: Alpha 3 gamma 3  0.2318315
4:  Beta 1 Delta 1  1.2640080

每当有空格 (" ") 时,我想拆分我的 id 列。最终数据集应如下所示。

      id numberid   id2 numberid2           y
1: Alpha        1 gamma         1 -1.45772675
2: Alpha        2 gamma         2 -1.07430118
3: Alpha        3 gamma         3 -0.53454071
4:  Beta        1 Delta         1 -0.05854228

我当时就知道如何做这一栏:

dt_m <- dt%>%separate(id,
         sep=" ", c("id","numberid"))
      id numberid     id2          y
1: Alpha        1 gamma 1  2.0789930
2: Alpha        2 gamma 2 -0.2528485
3: Alpha        3 gamma 3  0.1332267
4:  Beta        1 Delta 1  1.9299524

但我想在多列上使用 map 对其进行迭代。有谁知道方便的方法

  1. 在一组列上使用 map 迭代,返回一个数据框

  2. 并使用列作为索引和字符串(粘贴数字“id”和数字“id2”)?

我尝试过类似的方法,但它会产生一个空数据框

vars <- c("id","id2")
dt2 <- dt%>%map_df(vars,~separate(.x,sep=" ", c((.x), "number")))

非常感谢您的帮助

【问题讨论】:

标签: r loops purrr


【解决方案1】:

使用cSplit,这将允许您一次对多个列执行此操作。

splitstackshape::cSplit(dt, c('id', 'id2'), sep = ' ')

#            y  id_1 id_2 id2_1 id2_2
#1:  0.4037779 Alpha    1 gamma     1
#2: -0.3753461 Alpha    2 gamma     2
#3:  0.8014951 Alpha    3 gamma     3
#4: -1.3539683  Beta    1 Delta     1

【讨论】:

  • 感谢这对处理手头的问题非常有用!
  • 亲爱的@RonakShah,我有一个后续问题,是否可以使用cSplit 指定生成的列名(例如“id”“numberid”)?
  • 不..我不认为你可以在cSplit内做到这一点。
【解决方案2】:

我认为使用separate() 的更典型的 tidyverse 方法过于转向长格式并分开然后转向宽,但是当您要求map() 解决方案时,您可以执行以下操作。另请注意,您使用的 data.table 对数据框或 tibble 具有不同的索引行为。

library(data.table)
library(tidyverse)

vars <- c("id","id2")

imap(vars, ~separate(dt[, .x, with = FALSE], .x, sep=" ", c(.x, paste0("numberid", .y))))  %>%
  bind_cols(dt[, setdiff(names(dt), vars), with = FALSE])

      id numberid1   id2 numberid2           y
1: Alpha         1 gamma         1 -0.69201999
2: Alpha         2 gamma         2 -0.39839537
3: Alpha         3 gamma         3 -1.24125212
4:  Beta         1 Delta         1 -0.02165367

或者:

dt %>%
  rowid_to_column() %>%
  pivot_longer(-c(y, rowid)) %>%
  separate(value, c("id", "number")) %>%
  pivot_wider(names_from = name, values_from = c(id, number))

【讨论】:

  • 非常感谢您的回复,如果我使用数据框,您是否介意展示枢轴方法以及如何索引。考虑到代码的复杂性,我的感觉是 map 对变量进行迭代不是很方便。
  • 查看更新。我对索引和 data.table 的评论 - 这只是为了解释为什么使用 dt[, .x, with = FALSE] 而不是 dt[.x]。见cran.r-project.org/web/packages/data.table/vignettes/…
【解决方案3】:

fread 的选项来自data.table

library(data.table)
nm1 <- names(dt)[1:2]
nm2 <- paste0('number', nm1)
nm3 <- c(rbind(nm1, nm2))
setnames(dt[, c(list(y), lapply(.SD,  function(x) 
      fread(text = x))), .SDcols= nm1], c("y", nm3))[]

【讨论】:

    猜你喜欢
    • 2020-05-26
    • 1970-01-01
    • 2016-11-26
    • 1970-01-01
    • 2021-06-28
    • 1970-01-01
    • 2022-01-12
    • 2021-02-17
    相关资源
    最近更新 更多