2016-10-20 14 views
0

我的CSV文件中包含以下類型的數據集(ds1),其中包括類名和相應的故障。我打算使用R腳本從故障數等於2的數據中提取或過濾Package Name。使用R腳本從完全定義的類名提取包名

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 
+2

'grepl'會更合適嗎? – r2evans

+0

你可以使用'grepl'解決它嗎? –

+0

''/^([^\\.]+)/「'有一個嚴重問題:你使用的正則表達式分隔符'/'不應該在R表達式函數中使用。此外,當您在字符類中轉義'.'時,您將它設爲僅兼容PCRE的表達式(不再與TRE兼容)。但是,要在最後一個點之前獲得字符串,您需要使用'「^(。*)\\。」'(然後您在組1中有一個捕獲值)或PCRE''^。*(?= \ \「)」'(用'perl = TRUE')。 –

回答

1

grep(和grepl)不適合此:你是不是濾波基於文本內容。您正在(a)基於Faults進行過濾,和(b)更改Class中的文本。

您的數據:上Faults

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)) 

過濾(你已經有這個)。你只需要這兩個命令中的一個,它們都做同樣的事情;主要區別在於可讀性(個人偏好)和性能(第二個,在這種情況下,花費大約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使用這種方式是不是經常這樣的速度,在差與其他方法相比。它通常不是更快,但它往往不是一個數量級的慢。

+0

謝謝@ r2evans –

+0

它爲我工作 –

+0

@ r2evans - 尼斯基準。在這種情況下,我不希望dplyr慢得多。任何洞察力爲什麼? – egnha

0

你也可以做到這一點,沒有任何花哨的正則表達式的:在點拆分每個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建議的解決方案慢很多。

+0

你真的應該在你的解決方案中包含非基礎庫。不是每個人都能流利地知道這是使用'magrittr'。 – r2evans

+0

@ r2evans - 我忽略了這一點,謝謝。更改。 – egnha

0

我不認爲你正在尋找基於類名的過濾。 只需2步即可完成。

# Filter 
dschanged <- ds1[ds1$Faults == 2,] 
# Extract package name 
dschanged$class <- sub('(.*)[.](.*)','\\1',dschanged$class)