使用 R 脚本从完全定义的 class 名称中提取包名称
Extracting the Package name from fully defined class names using R scripting
我的 CSV 文件中有以下类型的数据集 (ds1),其中包括 class 名称和相应的故障。我打算使用 R 脚本从故障数等于 2 的数据中提取或过滤包名称。
Class Faults
org.apache.tools.ant.taskdefs.Definer 2
org.apache.tools.ant.taskdefs.Definer 2
org.apache.tools.ant.taskdefs.Delete 1
org.apache.tools.ant.taskdefs.Deltree 2
org.apache.tools.ant.taskdefs.DependSet 2
org.apache.tools.ant.taskdefs.DependSet 2
org.apache.tools.ant.taskdefs.DependSet 2
org.apache.tools.ant.taskdefs.Ear 2
org.apache.tools.ant.taskdefs.Ear 2
org.apache.tools.ant.taskdefs.Echo 1
org.apache.tools.ant.Exec 2
org.apache.tools.ant.Exec 2
我已经编写了以下代码,但是,它没有产生所需的输出
dschanged<- subset(ds1, grep( "/^([^\.]+)/", class) & Faults==2 )
从技术上讲,我需要适当的正则表达式来提取最后一个点 (.) 之前的字符串以生成以下输出。
org.apache.tools.ant.taskdefs 2
org.apache.tools.ant.taskdefs 2
org.apache.tools.ant.taskdefs 2
org.apache.tools.ant.taskdefs 2
org.apache.tools.ant.taskdefs 2
org.apache.tools.ant.taskdefs 2
org.apache.tools.ant.taskdefs 2
org.apache.tools.ant.taskdefs 2
org.apache.tools.ant 2
org.apache.tools.ant 2
您也可以在没有任何花哨的正则表达式的情况下执行此操作:在点上拆分每个 Class
字符串,然后点粘贴除最后一个子字符串之外的所有字符串。
library(magrittr) # Provides pipe operator `%>%`
dschanged <- subset(ds1, Faults == 2)
dschanged$Class <- dschanged$Class %>%
strsplit(split = "[.]") %>%
sapply(function(x) head(x, -1L) %>% paste(collapse = "."))
请注意,没有点的字符串将被转换为空字符串。它也比@r2evans 建议的解决方案慢很多。
我认为您不是在寻找基于 class 名称的过滤。
只需分两步完成。
# Filter
dschanged <- ds1[ds1$Faults == 2,]
# Extract package name
dschanged$class <- sub('(.*)[.](.*)','\1',dschanged$class)
grep
(和 grepl
)不适用于此:您没有根据文本内容进行过滤。您 (a) 基于 Faults
进行过滤,并且 (b) 更改 Class
.
中的文本
您的数据:
ds1 <- structure(list(Class = c("org.apache.tools.ant.taskdefs.Definer", "org.apache.tools.ant.taskdefs.Definer", "org.apache.tools.ant.taskdefs.Delete", "org.apache.tools.ant.taskdefs.Deltree", "org.apache.tools.ant.taskdefs.DependSet", "org.apache.tools.ant.taskdefs.DependSet", "org.apache.tools.ant.taskdefs.DependSet", "org.apache.tools.ant.taskdefs.Ear", "org.apache.tools.ant.taskdefs.Ear", "org.apache.tools.ant.taskdefs.Echo", "org.apache.tools.ant.Exec", "org.apache.tools.ant.Exec"),
Faults = c(2L, 2L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 1L, 2L, 2L)),
.Names = c("Class", "Faults"), class = "data.frame", row.names = c(NA, -12L))
过滤 Faults
(您已经有了这个)。您只需要这两个命令之一,它们都做同样的事情;主要区别在于可读性(个人偏好)和性能(第二个,在这种情况下,花费的时间减少了大约 35%,尽管因为它们都是以微秒为单位来衡量的,所以竞争似乎很愚蠢)。
ds2 <- subset(ds1, Faults == 2)
ds2 <- ds1[ds1$Faults == 2,]
更新 Class
以删除最后一个单词(和点):
ds2$Class <- gsub("\.[^.]*$", "", ds2$Class)
ds2
# Class Faults
# 1 org.apache.tools.ant.taskdefs 2
# 2 org.apache.tools.ant.taskdefs 2
# 4 org.apache.tools.ant.taskdefs 2
# 5 org.apache.tools.ant.taskdefs 2
# 6 org.apache.tools.ant.taskdefs 2
# 7 org.apache.tools.ant.taskdefs 2
# 8 org.apache.tools.ant.taskdefs 2
# 9 org.apache.tools.ant.taskdefs 2
# 11 org.apache.tools.ant 2
# 12 org.apache.tools.ant 2
注意:这也可以用 sub
而不是 gsub
来完成,但后者是我的第一个目标,因为我的大部分用途都处理更大和重复的正则表达式。两者之间的主要(唯一?)区别是:
'sub' and 'gsub' perform replacement of the first and all matches respectively
(来自 ?sub
)。
我知道没有工具可以在单个命令中 进行过滤和更改(尽管我不知道 data.table
可以)。
类似于@egnha 的解决方案(使用 magrittr
),这是一个使用 dplyr
的解决方案,许多人声称它非常容易阅读和适应(以潜在的性能成本为代价):
library(dplyr)
ds2 <- ds1 %>%
filter(Faults == 2) %>%
mutate(Class = gsub("\.[^.]*$", "", Class))
既然我提到了性能,这里有一个比较:
microbenchmark(indexing = { ds2 <- ds1[ds1$Faults == 2,]; ds2$Class <- gsub("\.[^.]*$", "", ds2$Class) },
subset = { ds2 <- subset(ds1, Faults == 2) ; ds2$Class <- gsub("\.[^.]*$", "", ds2$Class) },
dplyr = { ds1 %>% filter(Faults == 2) %>% mutate(Class = gsub("\.[^.]*$", "", Class)) })
# Unit: microseconds
# expr min lq mean median uq max neval
# indexing 71.841 87.7045 109.4496 104.2975 120.7075 269.493 100
# subset 102.473 115.6020 147.0108 139.1230 165.5620 287.726 100
# dplyr 1067.030 1156.3745 1323.1174 1225.4805 1351.2920 4270.308 100
郑重声明,与其他方法相比,以这种方式使用的 dplyr
并不经常这么慢。它通常不会 更快 ,但通常不会慢一个数量级。
我的 CSV 文件中有以下类型的数据集 (ds1),其中包括 class 名称和相应的故障。我打算使用 R 脚本从故障数等于 2 的数据中提取或过滤包名称。
Class Faults
org.apache.tools.ant.taskdefs.Definer 2
org.apache.tools.ant.taskdefs.Definer 2
org.apache.tools.ant.taskdefs.Delete 1
org.apache.tools.ant.taskdefs.Deltree 2
org.apache.tools.ant.taskdefs.DependSet 2
org.apache.tools.ant.taskdefs.DependSet 2
org.apache.tools.ant.taskdefs.DependSet 2
org.apache.tools.ant.taskdefs.Ear 2
org.apache.tools.ant.taskdefs.Ear 2
org.apache.tools.ant.taskdefs.Echo 1
org.apache.tools.ant.Exec 2
org.apache.tools.ant.Exec 2
我已经编写了以下代码,但是,它没有产生所需的输出
dschanged<- subset(ds1, grep( "/^([^\.]+)/", class) & Faults==2 )
从技术上讲,我需要适当的正则表达式来提取最后一个点 (.) 之前的字符串以生成以下输出。
org.apache.tools.ant.taskdefs 2
org.apache.tools.ant.taskdefs 2
org.apache.tools.ant.taskdefs 2
org.apache.tools.ant.taskdefs 2
org.apache.tools.ant.taskdefs 2
org.apache.tools.ant.taskdefs 2
org.apache.tools.ant.taskdefs 2
org.apache.tools.ant.taskdefs 2
org.apache.tools.ant 2
org.apache.tools.ant 2
您也可以在没有任何花哨的正则表达式的情况下执行此操作:在点上拆分每个 Class
字符串,然后点粘贴除最后一个子字符串之外的所有字符串。
library(magrittr) # Provides pipe operator `%>%`
dschanged <- subset(ds1, Faults == 2)
dschanged$Class <- dschanged$Class %>%
strsplit(split = "[.]") %>%
sapply(function(x) head(x, -1L) %>% paste(collapse = "."))
请注意,没有点的字符串将被转换为空字符串。它也比@r2evans 建议的解决方案慢很多。
我认为您不是在寻找基于 class 名称的过滤。 只需分两步完成。
# Filter
dschanged <- ds1[ds1$Faults == 2,]
# Extract package name
dschanged$class <- sub('(.*)[.](.*)','\1',dschanged$class)
grep
(和 grepl
)不适用于此:您没有根据文本内容进行过滤。您 (a) 基于 Faults
进行过滤,并且 (b) 更改 Class
.
您的数据:
ds1 <- structure(list(Class = c("org.apache.tools.ant.taskdefs.Definer", "org.apache.tools.ant.taskdefs.Definer", "org.apache.tools.ant.taskdefs.Delete", "org.apache.tools.ant.taskdefs.Deltree", "org.apache.tools.ant.taskdefs.DependSet", "org.apache.tools.ant.taskdefs.DependSet", "org.apache.tools.ant.taskdefs.DependSet", "org.apache.tools.ant.taskdefs.Ear", "org.apache.tools.ant.taskdefs.Ear", "org.apache.tools.ant.taskdefs.Echo", "org.apache.tools.ant.Exec", "org.apache.tools.ant.Exec"),
Faults = c(2L, 2L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 1L, 2L, 2L)),
.Names = c("Class", "Faults"), class = "data.frame", row.names = c(NA, -12L))
过滤 Faults
(您已经有了这个)。您只需要这两个命令之一,它们都做同样的事情;主要区别在于可读性(个人偏好)和性能(第二个,在这种情况下,花费的时间减少了大约 35%,尽管因为它们都是以微秒为单位来衡量的,所以竞争似乎很愚蠢)。
ds2 <- subset(ds1, Faults == 2)
ds2 <- ds1[ds1$Faults == 2,]
更新 Class
以删除最后一个单词(和点):
ds2$Class <- gsub("\.[^.]*$", "", ds2$Class)
ds2
# Class Faults
# 1 org.apache.tools.ant.taskdefs 2
# 2 org.apache.tools.ant.taskdefs 2
# 4 org.apache.tools.ant.taskdefs 2
# 5 org.apache.tools.ant.taskdefs 2
# 6 org.apache.tools.ant.taskdefs 2
# 7 org.apache.tools.ant.taskdefs 2
# 8 org.apache.tools.ant.taskdefs 2
# 9 org.apache.tools.ant.taskdefs 2
# 11 org.apache.tools.ant 2
# 12 org.apache.tools.ant 2
注意:这也可以用 sub
而不是 gsub
来完成,但后者是我的第一个目标,因为我的大部分用途都处理更大和重复的正则表达式。两者之间的主要(唯一?)区别是:
'sub' and 'gsub' perform replacement of the first and all matches respectively
(来自 ?sub
)。
我知道没有工具可以在单个命令中 进行过滤和更改(尽管我不知道 data.table
可以)。
类似于@egnha 的解决方案(使用 magrittr
),这是一个使用 dplyr
的解决方案,许多人声称它非常容易阅读和适应(以潜在的性能成本为代价):
library(dplyr)
ds2 <- ds1 %>%
filter(Faults == 2) %>%
mutate(Class = gsub("\.[^.]*$", "", Class))
既然我提到了性能,这里有一个比较:
microbenchmark(indexing = { ds2 <- ds1[ds1$Faults == 2,]; ds2$Class <- gsub("\.[^.]*$", "", ds2$Class) },
subset = { ds2 <- subset(ds1, Faults == 2) ; ds2$Class <- gsub("\.[^.]*$", "", ds2$Class) },
dplyr = { ds1 %>% filter(Faults == 2) %>% mutate(Class = gsub("\.[^.]*$", "", Class)) })
# Unit: microseconds
# expr min lq mean median uq max neval
# indexing 71.841 87.7045 109.4496 104.2975 120.7075 269.493 100
# subset 102.473 115.6020 147.0108 139.1230 165.5620 287.726 100
# dplyr 1067.030 1156.3745 1323.1174 1225.4805 1351.2920 4270.308 100
郑重声明,与其他方法相比,以这种方式使用的 dplyr
并不经常这么慢。它通常不会 更快 ,但通常不会慢一个数量级。