当所需变量的数量未知时如何使用 tidyr::separate [重复]

Posted

技术标签:

【中文标题】当所需变量的数量未知时如何使用 tidyr::separate [重复]【英文标题】:How to use tidyr::separate when the number of needed variables is unknown [duplicate] 【发布时间】:2016-01-22 04:25:52 【问题描述】:

我有一个包含电子邮件通信的数据集。一个例子:

library(dplyr)
library(tidyr)

dat <- data_frame('date' = Sys.time(), 
                  'from' = c("person1@gmail.com", "person2@yahoo.com", 
                             "person3@hotmail.com", "person4@msn.com"), 
                  'to' = c("person2@yahoo.com,person3@hotmail.com", "person3@hotmail.com", 
                           "person4@msn.com,person1@gmail.com,person2@yahoo.com", "person1@gmail.com"))

在上面的例子中,很容易看出我需要多少个变量,所以我可以执行以下操作:

dat %>% separate(to, into = paste0("to_", 1:3), sep = ",", extra = "merge", fill = "right")

#Source: local data frame [4 x 5]
#
#                 date                from                to_1                to_2              to_3
#               (time)               (chr)               (chr)               (chr)             (chr)
#1 2015-10-22 14:52:41   person1@gmail.com   person2@yahoo.com person3@hotmail.com                NA
#2 2015-10-22 14:52:41   person2@yahoo.com person3@hotmail.com                  NA                NA
#3 2015-10-22 14:52:41 person3@hotmail.com     person4@msn.com   person1@gmail.com person2@yahoo.com
#4 2015-10-22 14:52:41     person4@msn.com   person1@gmail.com                  NA                NA

但是,我的数据集有 4,000 条记录,我不希望通过查找其中元素数量最多的行来确定需要创建多少变量。我处理这个问题的方法是首先自己拆分列并获取每个拆分的长度,然后找到最大值:

n_vars <- dat$to %>% str_split(",") %>% lapply(function(z) length(z)) %>% unlist() %>% max()

但这似乎效率低下。有更好的方法吗?

【问题讨论】:

也可以library(data.table) ; cbind(dat, setDT(dat)[, tstrsplit(to, ",")]) 似乎是一个足够合理的解决方案,而不是加载另一个包。如果您已经在加载 tidyverse 可以使用 map_dbl 并删除 unlist 使其稍微干净一些。 dat$to %&gt;% str_split(",") %&gt;% map_dbl(~ length(.)) %&gt;% max() 您可以更巧妙地计算 n_vars 而无需使用n_vars &lt;- dat$to %&gt;% str_count(pattern = ",") %&gt;% max() + 1进行拆分 【参考方案1】:

这是个好问题——我通常的回答是使用strsplit,然后使用unnestspread,这也不是很高效:

library(dplyr)
library(tidyr)

dat %>% mutate(to = strsplit(to, ",")) %>%
        unnest(to) %>%
        group_by(from) %>%
        mutate(row = row_number()) %>%
        spread(row, to)

Source: local data frame [4 x 5]

                 date                from                   1                   2                 3
               (time)               (chr)               (chr)               (chr)             (chr)
1 2015-10-22 15:03:17   person1@gmail.com   person2@yahoo.com person3@hotmail.com                NA
2 2015-10-22 15:03:17   person2@yahoo.com person3@hotmail.com                  NA                NA
3 2015-10-22 15:03:17 person3@hotmail.com     person4@msn.com   person1@gmail.com person2@yahoo.com
4 2015-10-22 15:03:17     person4@msn.com   person1@gmail.com                  NA                NA

【讨论】:

我认为这样更好,因为你可以选择不传播到最后。将电子邮件分成所有这些单独的列似乎很愚蠢。 @bramtayl 我有一种感觉,故意分开让这很难,所以你最终不会得到宽数据而不是长数据 @bramtayl 我同意在这种情况下拥有广泛的数据没有意义(在大多数情况下也没有意义),但这是一个简单的概念,可以让你绕着头去了解底层当您不知道需要多少新列时使用separate 的问题。 Akrun 的解决方案仍然是一个不错的解决方案,因为您将 direction = "long" 设置为在一列中获取所有电子邮件。 请注意,如果您不想要宽数据集,只需在 unnest 处停止命令,那么您最终会得到 long 数据格式【参考方案2】:

我们可以使用cSplit

library(splitstackshape) 
cSplit(dat, 'to', ',')

【讨论】:

以上是关于当所需变量的数量未知时如何使用 tidyr::separate [重复]的主要内容,如果未能解决你的问题,请参考以下文章

当所需的文本框为空时,如何强制页面回发

当所需的触摸次数超过一次时,如何获得 UILongPressGestureRecognizer 的触摸位置?

当变量数量未知时插入Sqlalchemy

Perl 中的正则表达式组:如何从正则表达式组中捕获与字符串中出现的未知数量/多个/变量匹配的元素到数组中?

可以扩展 x 数量的选项和值组合的查询

如何在 html 表中为未知数量的输入命名?