【问题标题】:Create multiple columns *of different format* from a single column and clean up results [closed]从单列创建多列*不同格式*并清理结果[关闭]
【发布时间】:2016-05-04 15:30:10
【问题描述】:

正如标题所暗示的那样,这个问题是这个类似标题的question 的后续问题。在那里,我询问了如何使用分隔符 _ 将数据帧的字符列拆分为多个数字列,并清理结果。在这种情况下,所有列都是数字,并且它们是从拆分列的以下元素创建的,因此解决方案更容易。这一次,情况有点不同:

foo <- data.frame(Point.Type = c("Zero Start","Zero Start", "Zero Start", "3000rpm_10%_13barG_Sdsdsa_1.0_F_Pww","3000rpm_10%_13barG_Sdsdsa_1.0_F_Pww","3000rpm_10%_13barG_Sdsdsa_1.0_R_Pww","Zero Stop","Zero Start"),
               Point.Value = c(NA,NA,NA,rnorm(3),NA,NA))

Point.Type 列,我需要创建四个列,rpmGVFp0Setup

  • rpmGVFp0 必须是 numericinteger 类型,而 Setup 必须是 character 类型。
  • 如果Point.Type 不包含_(在我的示例中为第1、2、3、7、8 行),则所有四个新列都必须设置为NA
  • 如果Point.Type 确实包含_,那么rpmGVFp0 必须包含Point.Type 的前三个元素,从所有非数字字符中“清除”。如果Point.Type的第6个元素等于F,则Setup必须等于Full,否则必须等于Reduced。在我的示例中,这意味着 Setup 对于第 4 行和第 5 行应该等于 Full,对于第 6 行应该等于 Reduced

为了获得三个 numeric 列,我使用了来自 @Procrastinatus_Maximus 的优秀解决方案,这里稍微改写一下:

library(dplyr)
foo <- foo %>%
  separate(Point.Type, c("rpm", "GVF", "p0"), 
           sep="_", remove = FALSE, extra="drop", fill="right") %>%
  mutate_each(funs(as.numeric(gsub("[^0-9]","",.))), rpm, GVF, p0) 

现在,问题出在characterSetup。只是天真地写

library(dplyr)
foo <- foo %>%
  separate(Point.Type, c("rpm", "GVF", "p0","Setup"), 
           sep="_", remove = FALSE, extra="drop", fill="right") %>%
  mutate_each(funs(as.numeric(gsub("[^0-9]","",.))), rpm, GVF, p0,Setup) 

不起作用,因为Setup 的值与紧跟在p0 之后的Point.Type 的元素无关。此外,Setup 的值取决于Point.Type 的第 6 个元素是F 还是R,但这些是character 值,它们只是从mutate_each(funs(as.numeric(gsub("[^0-9]","",.))),... 中扫除。我得到了这段代码的某个地方:

library(dplyr)
foo <- foo %>%
  separate(Point.Type, c("rpm", "GVF", "p0"), 
           sep="_", remove = FALSE, extra="drop", fill="right") %>%
  mutate_each(funs(as.numeric(gsub("[^0-9]","",.))), rpm, GVF, p0) 
library(stringr)
foo$Setup <- ifelse(str_split_fixed(setup$Point.Type,"_",7)[,6]=="F",
                                 "Full","Reduced") 

这给了我

                           Point.Type  rpm GVF p0 Point.Value   Setup
1                          Zero Start   NA  NA NA          NA Reduced
2                          Zero Start   NA  NA NA          NA Reduced
3                          Zero Start   NA  NA NA          NA Reduced
4 3000rpm_10%_13barG_Sdsdsa_1.0_F_Pww 3000  10 13   1.9188554    Full
5 3000rpm_10%_13barG_Sdsdsa_1.0_F_Pww 3000  10 13  -0.5743683    Full
6 3000rpm_10%_13barG_Sdsdsa_1.0_R_Pww 3000  10 13  -0.7122796 Reduced
7                           Zero Stop   NA  NA NA          NA Reduced
8                          Zero Start   NA  NA NA          NA Reduced

但是,如您所见,它仍然不起作用:Setup 等于 Reduced,在应该等于 NA 的情况下也是如此。另外,坦率地说,我不喜欢仅仅为了创建Setup 而加载stringr 的想法。我更愿意在dplyr 中完成所有工作,最好是使用管道在一行代码中完成。如果这导致代码不可读,那么对dplyr 的两次连续调用也可以。

【问题讨论】:

  • 我真的不明白这个问题会“太宽泛”,而前一个问题(这只是一个希望的简单扩展)一点也不宽泛。为什么要求再管理一个专栏会使问题过于宽泛?

标签: r split dplyr


【解决方案1】:

这是我的尝试。我想这就是你所要求的。我举了你最后一个例子,并在链的末尾添加了一个变异。

library(dplyr)
library(tidyr)

foo <- data.frame(Point.Type = c("Zero Start","Zero Start", "Zero Start", "3000rpm_10%_13barG_Sdsdsa_1.0_F_Pww","3000rpm_10%_13barG_Sdsdsa_1.0_F_Pww","3000rpm_10%_13barG_Sdsdsa_1.0_R_Pww","Zero Stop","Zero Start"),
                  Point.Value = c(NA,NA,NA,rnorm(3),NA,NA))

res <- foo %>%
  separate(Point.Type, c("rpm", "GVF", "p0"), 
           sep="_", remove = FALSE, extra="drop", fill="right") %>%
  mutate_each(funs(as.numeric(gsub("[^0-9]","",.))), rpm, GVF, p0) %>%
  mutate(Setup = ifelse(!is.na(rpm), ifelse(grepl("_F_", Point.Type),"Full", "Reduced"),NA))

【讨论】:

  • 有效!我不明白为什么Setup 中的NA 看起来与其他三列中的不同(R 将它们打印到屏幕上为&lt;NA&gt; 而不是NA)。但是,R 似乎可以很好地处理它们,所以这对我来说没问题。
  • @DeltaIV 它显示为 的原因是为了将其与 NA 字符条目区分开来,例如北美的缩写。在单个矢量文本中显示引用,在数据框中它不显示引用,因此 NA 在它们周围得到 。
  • 好的,所以,numeric 列(rpmGVFp0)中的 NA 没有得到 ,因为它们是数字,所以没有与字符串 "NA" 混淆。在Setup 列中,即character,R 添加 以将它们与所述字符串区分开来。明白了。谢谢!
猜你喜欢
  • 2016-05-14
  • 2017-11-24
  • 2023-03-10
  • 1970-01-01
  • 2015-04-03
  • 2022-01-23
  • 2023-03-31
  • 2023-03-23
  • 2016-03-27
相关资源
最近更新 更多