R 从单个列创建多个列并清理结果

R 从单个列创建多个列并清理结果,r,split,tidyr,R,Split,Tidyr,我有这样一个数据框: foo=data.frame(Point.Type = c("Zero Start","Zero Start", "Zero Start", "3000rpm_10%_13barG_Sdsdsa_1.0_ss_Pww","3000rpm_10%_13barG_Sdsdsa_1.0_ss_Pww","3000rpm_10%_13barG_Sdsdsa_1.0_ss_Pww","Zero Stop","Zero Start"), Point.Val

我有这样一个数据框:

foo=data.frame(Point.Type = c("Zero Start","Zero Start", "Zero Start", "3000rpm_10%_13barG_Sdsdsa_1.0_ss_Pww","3000rpm_10%_13barG_Sdsdsa_1.0_ss_Pww","3000rpm_10%_13barG_Sdsdsa_1.0_ss_Pww","Zero Stop","Zero Start"),
               Point.Value = c(NA,NA,NA,rnorm(3),NA,NA))
我想通过使用分隔符
\uu
拆分第一列来添加三列,并且只保留拆分后获得的数值。对于第一列不包含任何
的行,三个新列应为
NA
。我使用
separate
获得了一些成功,但这还不够:

> library(tidyr) 
> bar = separate(foo,Point.Type, c("rpm_nom", "GVF_nom", "p0in_nom"), sep="_", remove = FALSE, extra="drop", fill="right")
> bar
                            Point.Type    rpm_nom GVF_nom p0in_nom Point.Value
1                           Zero Start Zero Start    <NA>     <NA>          NA
2                           Zero Start Zero Start    <NA>     <NA>          NA
3                           Zero Start Zero Start    <NA>     <NA>          NA
4 3000rpm_10%_13barG_Sdsdsa_1.0_ss_Pww    3000rpm     10%   13barG   -1.468033
5 3000rpm_10%_13barG_Sdsdsa_1.0_ss_Pww    3000rpm     10%   13barG    1.280868
6 3000rpm_10%_13barG_Sdsdsa_1.0_ss_Pww    3000rpm     10%   13barG    0.270126
7                            Zero Stop  Zero Stop    <NA>     <NA>          NA
8                           Zero Start Zero Start    <NA>     <NA>          NA
>库(tidyr)
>条=单独的(foo,Point.Type,c(“rpm_nom”,“GVF_nom”,“p0in_nom”),sep=“”,remove=FALSE,extra=“drop”,fill=“right”)
>酒吧
点。键入rpm_nom GVF_nom p0in_nom Point.Value
1零开始零开始NA
2零开始零开始NA
3零开始零开始NA
4 3000rpm_10%_13barG_SDSA_1.0_不锈钢Pww 3000rpm 10%13barG-1.468033
5 3000rpm 10%13barG SDSA 1.0不锈钢Pww 3000rpm 10%13barG 1.280868
6 3000rpm 10%13barG SDSA 1.0不锈钢Pww 3000rpm 10%13barG 0.270126
7零停止零停止NA
8零开始零开始NA
我不知道为什么我的数据框现在包含两种明显不同的
NA
,但
是。NA
似乎喜欢这两种,所以我可以接受。但是,我有两种问题:

  • 新列应至少为
    数值
    ,也可能为
    整数
    。相反,它们是
    字符
    ,因为尾随
    rpm
    %
    barG
    。我怎样才能摆脱这些
  • 当无法拆分
    点类型时,
    rpm\u nom
    应为
    NA
    ,而变为
    零开始
    零停止
    。更改
    fill=
    选项只会更改新列中获得
    Zero Start
    /
    Zero Stop
    的列。相反,我希望这三个都是
    NA
    。我该怎么做

  • 注意:我使用的是
    tidyr
    ,但如果您认为有更好的方法,当然不需要这样做。

    您可以使用dplyr对列进行后期处理:


    或者使用data.table(由@DavidArenburg在评论中提供):

    将产生类似的结果:

    > foo
                                 Point.Type Point.Value rpm_nom GVF_nom p0in_nom
    1:                           Zero Start          NA      NA      NA       NA
    2:                           Zero Start          NA      NA      NA       NA
    3:                           Zero Start          NA      NA      NA       NA
    4: 3000rpm_10%_13barG_Sdsdsa_1.0_ss_Pww -0.09255445    3000      10       13
    5: 3000rpm_10%_13barG_Sdsdsa_1.0_ss_Pww  1.18581340    3000      10       13
    6: 3000rpm_10%_13barG_Sdsdsa_1.0_ss_Pww  2.14475950    3000      10       13
    7:                            Zero Stop          NA      NA      NA       NA
    8:                           Zero Start          NA      NA      NA       NA
    

    这样做的好处是,
    foo
    通过引用进行更新。由于这种方法速度更快、内存效率更高,因此对于使用大型数据集尤其有价值。

    对于
    base R
    ,我们可以在必要时首先强制
    NA
    值,并强制类
    数值

    bar[-1] <- lapply(bar[-1], function(x) {
      is.na(x) <- grepl("Zero", x)
      as.numeric(gsub("[^0-9.]", "", x))})
    #                             Point.Type rpm_nom GVF_nom p0in_nom Point.Value
    # 1                           Zero Start      NA      NA       NA          NA
    # 2                           Zero Start      NA      NA       NA          NA
    # 3                           Zero Start      NA      NA       NA          NA
    # 4 3000rpm_10%_13barG_Sdsdsa_1.0_ss_Pww    3000      10       13   0.3558397
    # 5 3000rpm_10%_13barG_Sdsdsa_1.0_ss_Pww    3000      10       13   1.1454829
    # 6 3000rpm_10%_13barG_Sdsdsa_1.0_ss_Pww    3000      10       13   0.2958815
    # 7                            Zero Stop      NA      NA       NA          NA
    # 8                           Zero Start      NA      NA       NA          NA
    

    bar[-1]@Jaap听起来很棒!使用
    %>%
    ,是否可以避免创建
    ?@davidernburg您的解决方案看起来也不错,但是
    数据表是什么?我所有的代码都在data.frames上工作。我担心切换到这些数据表可能会影响代码的其余部分。另外,我不知道函数
    tstrsplit
    ,但我想它在
    data.table
    包中有记录。@DeltaIV更新了答案。
    data.table
    data.frame
    的一种增强形式。有关更多信息,请参阅。有趣!我的数据帧并不是很大,但比示例要大得多(大约是2000行乘1200列)。也许数据表会很好:我会研究它们。我有点遗憾地放弃了哈德利·维克汉姆的软件包,因为我喜欢它们,但是如果性能得到了实质性的提升,那么它可能是值得的!顺便说一句,您可以使用
    type.convert
    ,而不是
    作为.numeric
    ,这样它将自己正确地转换为
    整数和
    numeric
    。我不确定您为什么要使用
    条[-1]
    。另外,@Jaap
    gsub([^0-9],”,x)
    和您的
    gsub([[:alpha:].[:punct:][],”,x)
    之间有什么区别?最后,为什么在上一列中,您会得到10^14量级的
    Point.Value
    s
    rnorm(3)
    应该生成更接近0的数字。
    bar[-1]
    删除我们不想处理的第一列。这两种正则表达式模式之间的差异可以在这里看到。在最后一列中,删除了小数点。
    library(data.table)
    setDT(foo)[, c("rpm_nom","GVF_nom","p0in_nom") := 
                 lapply(tstrsplit(Point.Type, "_", fixed = TRUE)[1:3],
                        function(x) as.numeric(gsub("[^0-9]","",x)))
               ]
    
    > foo
                                 Point.Type Point.Value rpm_nom GVF_nom p0in_nom
    1:                           Zero Start          NA      NA      NA       NA
    2:                           Zero Start          NA      NA      NA       NA
    3:                           Zero Start          NA      NA      NA       NA
    4: 3000rpm_10%_13barG_Sdsdsa_1.0_ss_Pww -0.09255445    3000      10       13
    5: 3000rpm_10%_13barG_Sdsdsa_1.0_ss_Pww  1.18581340    3000      10       13
    6: 3000rpm_10%_13barG_Sdsdsa_1.0_ss_Pww  2.14475950    3000      10       13
    7:                            Zero Stop          NA      NA      NA       NA
    8:                           Zero Start          NA      NA      NA       NA
    
    bar[-1] <- lapply(bar[-1], function(x) {
      is.na(x) <- grepl("Zero", x)
      as.numeric(gsub("[^0-9.]", "", x))})
    #                             Point.Type rpm_nom GVF_nom p0in_nom Point.Value
    # 1                           Zero Start      NA      NA       NA          NA
    # 2                           Zero Start      NA      NA       NA          NA
    # 3                           Zero Start      NA      NA       NA          NA
    # 4 3000rpm_10%_13barG_Sdsdsa_1.0_ss_Pww    3000      10       13   0.3558397
    # 5 3000rpm_10%_13barG_Sdsdsa_1.0_ss_Pww    3000      10       13   1.1454829
    # 6 3000rpm_10%_13barG_Sdsdsa_1.0_ss_Pww    3000      10       13   0.2958815
    # 7                            Zero Stop      NA      NA       NA          NA
    # 8                           Zero Start      NA      NA       NA          NA
    
    bar[-1] <- lapply(bar[-1], function(x) as.numeric(gsub("[^0-9.]", "", x)))