आर

2017-11-21 34 views
6

में एक स्ट्रिंग से सबस्ट्रिंग और संख्या निकालें मेरे पास कई उदाहरण हैं, कुछ उदाहरण हैं।आर

rfoutputtablep7q10000t20000c100 
rfoutputtablep7q1000t20000c100 
svmLinear2outputtablep7q20000t20000c100 
svmLinear2outputtablep7q5000t20000c100 

मैं कॉलम के साथ एक डेटा फ्रेम बनाना चाहते: algorithm, p, q, t, और c और इन तार से मान एक्सट्रैक्ट। तो "outputtable" से पहले सामान algorithm है, "p" के बाद नंबर p का मूल्य है, "q" के बाद नंबर q का मूल्य है, आदि

कैसे इस डेटा फ्रेम बनाया जा सकता है?

+0

कुछ बार '' tidyr :: अलग''' का उपयोग करें :) – rsmith54

+0

आप नियमित अभिव्यक्तियों का उपयोग कर सकते हैं। – kurdy

+0

नियमित अभिव्यक्तियां मुझे भ्रमित कर रही हैं। यदि आप मेरी मदद कर सकते हैं तो मैं वास्तव में इसकी सराहना करता हूं। मैं अभी भी बहुत शुरुआत कर रहा हूं :( –

उत्तर

5

केवल बेस आर का उपयोग करना।

res <- do.call(rbind, strsplit(y, 'outputtable|p|q|t|c')) 
res <- as.data.frame(res[, -2]) 
res[-1] <- lapply(res[-1], function(x) as.numeric(as.character(x))) 
names(res) <- c("algorithm", "p", "q", "t", "c") 
res 
# algorithm p  q  t c 
#1   rf 7 10000 20000 100 
#2   rf 7 1000 20000 100 
#3 svmLinear2 7 20000 20000 100 
#4 svmLinear2 7 5000 20000 100 

डेटा।

y <- scan(text = '"rfoutputtablep7q10000t20000c100" 
"rfoutputtablep7q1000t20000c100" 
"svmLinear2outputtablep7q20000t20000c100" 
"svmLinear2outputtablep7q5000t20000c100"', 
what = character()) 
+2

'सेटनाम (डेटा.फ्रेम (do.call (rbind, strsplit (x,' outputtable \\ डी | पी | क्यू | टी | सी ')), सी ("ए" , "पी", "क्यू", "टी", "सी")) ' –

+0

@ डीबी यह काम करता है लेकिन क्यों \\ डी'? क्या यह किसी भी दशमलव अंक की अस्वीकृति नहीं है? (मैं इसे देख रहा हूं [regex] (http://127.0.0.1:16932/library/base/html/regex.html)।) –

+1

@ डीबी मैंने अभी '\\ डी' के बजाय बिंदु' .' का उपयोग करने का प्रयास किया है, और यह काम करता है। –

4
library(stringr) 
myd = c("p", "q", "t", "c") 
data.frame(sapply(myd, function(a) str_extract(str_extract(x, paste0(a, "\\d+")), "\\d+"))) 
# p  q  t c 
#1 7 10000 20000 100 
#2 7 1000 20000 100 
#3 7 20000 20000 100 
#4 7 5000 20000 100 

#For first column 
substr(x, 1, unlist(gregexpr("outputtable", x)) - 1) 
#[1] "rf"   "rf"   "svmLinear2" "svmLinear2" 

आंकड़े

x = c("rfoutputtablep7q10000t20000c100", "rfoutputtablep7q1000t20000c100", 
"svmLinear2outputtablep7q20000t20000c100", "svmLinear2outputtablep7q5000t20000c100") 
4

एक सकारात्मक देखो आगे का प्रयोग एल्गोरिथ्म पाने के लिए: पी के लिए https://regex101.com/r/7vDK1x/2

एक सकारात्मक लुक-पीछे:

gsub("^(\\w+)(?=outputtable).*", "\\1", string, perl=TRUE) 

लाइव उदाहरण , क्यू, टी, और सी (अन्य अक्षरों के साथ पी बदलें (?<=p)

gsub(".*?(?<=q)(\\d+).*", "\\1", a, perl=TRUE) 
2
यहाँ

एक और समाधान stringi पैकेज का उपयोग। अब तक प्रस्तावित सभी समाधानों की तुलना में बेंचमार्क की जांच करें। stringi आधार आर से थोड़ा तेज है, लेकिन निश्चित रूप से, यदि आप एक साधारण समाधान चाहते हैं तो थोड़ा और जटिल है। इसलिए, गति या सादगी के लिए आपकी वरीयता के आधार पर या तो अच्छा है। हालांकि, स्ट्रिंग अधिक जटिल मामलों के लिए अधिक लचीलापन प्रदान करता है। (ध्यान दें, मानक पूरी तरह से तुलनीय क्योंकि हम सभी data.frame की स्थापना और प्रकार परिवर्तित करने के लिए slighlty अलग दृष्टिकोण का इस्तेमाल किया है नहीं कर रहे हैं।)

अद्यतन:Rui Barradas की टिप्पणी के जवाब में मैं अपने जवाब देने के लिए कोड को अद्यतन किया है । (i) मैंने stringi दृष्टिकोण का उपयोग करके एक फ़ंक्शन का प्रस्ताव दिया है जिसमें कॉलम का संख्या संख्यात्मक रूप से रूपांतरण शामिल है, इसलिए, पूर्ण कार्य के लिए मैं इसे करूँगा। (ii) इसके अलावा, मैंने बेंचमार्क जोड़े हैं ताकि अब तक प्रस्तावित सभी दृष्टिकोण (टिप्पणियों में भी) शामिल हैं। आधा रास्ते निष्पक्ष तुलना प्राप्त करने के लिए मैंने प्रस्तावित दृष्टिकोणों को संशोधित किया है, ताकि आउटपुट समान हो। मैंने तुलनात्मक रूप से तुलनात्मक रूप से कॉलम के रूपांतरण को छोड़ दिया है, विशेष रूप से, और कमांड को अंतरिम असाइनमेंट से बचकर समान रूप से संक्षिप्त किया है।

ऐसा लगता है कि stringi अभी भी सबसे तेज़ है।

कृपया मुझे सही करें, अगर मैंने निष्पक्ष तुलना से संबंधित कुछ भी देखा है (विशेष रूप से stringr समाधान को भी सुधार किया जा सकता है, मुझे लगता है, लेकिन मैं पैकेज से इतना परिचित नहीं हूं, इसलिए मैंने प्रस्तावित समाधान रखा है)।

library(stringi) 
library(stringr) 
library(microbenchmark) 

strings <- c("rfoutputtablep7q10000t20000c100", 
       "rfoutputtablep7q1000t20000c100", 
      "svmLinear2outputtablep7q20000t20000c100", 
      "svmLinear2outputtablep7q5000t20000c100") 


split_to_df <- function(string, splititems, colidschar, firstcolname, replsplit_tonames) { 

    data <- as.data.frame(do.call(rbind 
           ,stri_split_regex(strings, paste(splititems, collapse = "|"))) 
         ,stringsAsFactors = FALSE) 
    names(data) <- c(firstcolname, stri_replace_all_regex(splititems, replsplit_tonames, "")) 
    numericcols <- setdiff(1:ncol(data), colidschar) 
    data[,numericcols] <- lapply(data[,numericcols], as.numeric) 
    return(data) 

} 

stringi_approach_complete <- function() { 

    df <- split_to_df(string = strings 
        ,splititems = c("outputtablep(?=\\d)", "q(?=\\d)", "t(?=\\d)", "c(?=\\d)") 
        ,colidschar = 1 
        ,firstcolname = "A" 
        ,replsplit_tonames = "\\(.*\\)|outputtable") 
    # class(df$p) 
    # [1] "numeric" 
    # A p  q  t c 
    # 1   rf 7 10000 20000 100 
    # 2   rf 7 1000 20000 100 
    # 3 svmLinear2 7 20000 20000 100 
    # 4 svmLinear2 7 5000 20000 100 

} 


stringi_approach_compare <- function() { 

    data <- as.data.frame(do.call(rbind, stri_split_regex(strings, c("outputtable|p(?=\\d)|q(?=\\d)|t(?=\\d)|c(?=\\d)")))) 
    names(data) <- c("A", "p", "q", "t", "c") 
    #class(data$p) 
    #[1] "factor" 
    #data 
    # A p  q  t c 
    # 1   rf 7 10000 20000 100 
    # 2   rf 7 1000 20000 100 
    # 3 svmLinear2 7 20000 20000 100 
    # 4 svmLinear2 7 5000 20000 100 

} 


stringr_approach <- function() { 

    res <- data.frame(p = str_extract(str_extract(strings, "p\\d+"), "\\d+"), 
        q = str_extract(str_extract(strings, "q\\d+"), "\\d+"), 
        t = str_extract(str_extract(strings, "t\\d+"), "\\d+"), 
        c = str_extract(str_extract(strings, "c\\d+"), "\\d+")) 
    #class(res$p) 
    #[1] "factor" 
    #res 
    # p  q  t c 
    # 1 7 10000 20000 100 
    # 2 7 1000 20000 100 
    # 3 7 20000 20000 100 
    # 4 7 5000 20000 100 

} 

base_approach1 <- function() { 

    res <- do.call(rbind, strsplit(strings, 'outputtable|p|q|t|c')) 
    res <- as.data.frame(res[, -2]) 
    names(res) <- c("A", "p", "q", "t", "c") 
    #class(res$p) 
    #[1] "factor" 
    #res[-1] <- lapply(res[-1], function(x) as.numeric(as.character(x))) 
    #res 
    #   A p  q  t c 
    #1   rf 7 10000 20000 100 
    #2   rf 7 1000 20000 100 
    #3 svmLinear2 7 20000 20000 100 
    #4 svmLinear2 7 5000 20000 100 


} 

base_approach2 <- function() { 

    df <- setNames(data.frame(do.call(rbind, strsplit(strings, 'outputtable\\D|p|q|t|c'))), c("A", "p", "q", "t", "c")) 
    #class(df$p) 
    #[1] "factor" 
    #df 
    # A p  q  t c 
    # 1   rf 7 10000 20000 100 
    # 2   rf 7 1000 20000 100 
    # 3 svmLinear2 7 20000 20000 100 
    # 4 svmLinear2 7 5000 20000 100 

} 



microbenchmark(
    base_approach1(), 
    base_approach2(), 
    stringi_approach_compare(), 
    stringr_approach(), 
    stringi_approach_complete() 

) 

# Unit: microseconds 
#   expr     min  lq  mean median  uq  max neval 
# base_approach1()   260.139 273.3635 337.1985 285.6005 298.2330 5280.152 100 
# base_approach2()   352.906 362.1820 461.8205 374.8140 391.9850 4645.791 100 
# stringi_approach_compare() 280.667 297.8380 312.8426 307.3125 319.1545 654.098 100 
# stringr_approach()   849.499 867.6570 956.7596 886.2100 923.7115 5651.609 100 
# stringi_approach_complete() 319.747 333.9580 461.5521 346.7870 369.0900 10985.052 100 
+0

क्या आप मेरे उत्तर में टिप्पणी में @ डीबी वन-लाइनर को बेंचमार्क भी कर सकते हैं? यह सबसे तेज़ प्रतीत होता है। वैसे भी, ऊपर की ओर। –

+0

यकीन है, अच्छा विचार, टिप्पणियों में ध्यान नहीं दिया है, क्षमा करें, मैं इसे करूँगा आने वाला कल... –