2017-01-13 81 views
0

我有以下數據框:從字符串中提取數字基礎上的分隔符

a <- seq(1:5) 
b <- c("abc_a_123456_defghij_1", "abc_a_78912_abc_2", "abc_a_345678912_xyzabc_3", 
          "abc_b_34567_defgh_4", "abc_c_891234556778_ijklmnop_5") 
df <- data.frame(a, b) 
df$b <- as.character(df$b) 

,我需要提取DF $ B而來的第二個和第三個下劃線的數量和分配給DF $ C。

我猜這是一個相當簡單的解決方案,但還沒有找到它。實際的數據集相當大(3MM行),因此效率是一個因素。

感謝您的幫助!

+0

爲什麼要給我們'a'?似乎只有'b'才能解決這個問題,不是嗎? –

+0

你是對的,一個是沒有必要的,對不起, – Michael

+2

好像'sub(「。* _(\\ d +)_。*」,「\\ 1」,b)'可能工作。 –

回答

1

創建一個my_split函數,該函數使用gregexpr來查找「_」的開始和結束位置。然後使用substr提取開始位置和結束位置之間的字符串。

my_split <- function(x, start, end){ 
    a1 <- gregexpr("_", x) 
    substr(x, a1[[1]][start]+1, a1[[1]][end]-1) 
} 

b <- c("abc_a_123456_defghij_1", "abc_a_78912_abc_2", "abc_a_345678912_xyzabc_3", "abc_b_34567_defgh_4", "abc_c_891234556778_ijklmnop_5") 

sapply(b, my_split, start = 2, end = 3) 
# abc_a_123456_defghij_1    abc_a_78912_abc_2 
# "123456"      "78912" 
# abc_a_345678912_xyzabc_3   abc_b_34567_defgh_4 
# "345678912"      "34567" 
# abc_c_891234556778_ijklmnop_5 
# "891234556778" 

使用data.table庫

library(data.table) 
setDT(df)[, c := lapply(b, my_split, start = 2, end = 3)] 
df 
# a        b   c 
# 1: 1  abc_a_123456_defghij_1  123456 
# 2: 2    abc_a_78912_abc_2  78912 
# 3: 3  abc_a_345678912_xyzabc_3 345678912 
# 4: 4   abc_b_34567_defgh_4  34567 
# 5: 5 abc_c_891234556778_ijklmnop_5 891234556778 

數據:

a <- seq(1:5) 
b <- c("abc_a_123456_defghij_1", "abc_a_78912_abc_2", "abc_a_345678912_xyzabc_3", "abc_b_34567_defgh_4", "abc_c_891234556778_ijklmnop_5") 
df <- data.frame(a, b, stringsAsFactors = FALSE) 
+0

你可以玩弄開始和結束值 – Sathish

4

我們可以用sub到不是一個_[^_]*)的zeor或多個字符從一開始匹配(^)後跟一個下劃線(_),然後另一組字符不是下劃線foll用下劃線義舉,捕捉其次是下劃線和其他字符組((\\d+))在隨後更多的數字的一個,然後用逆向引用該組取代它,並最終將其轉換爲numeric

as.numeric(sub("^[^_]*_[^_]+_(\\d+)_.*", "\\1", df$b)) 
#[1]  123456  78912 345678912  34567 891234556778