2014-02-22 41 views
4

我有一個大型數據集,其中所有列標題都是單個IDS,每個IDS長度爲8個字符。我想將這些單獨的ID分成兩行,第一行ID包含前7個字符,第二行僅包含最後一個字符。按R中的字母/字符數拆分列標籤

當前數據集:

ID1: Indiv01A Indiv01B Indiv02A Indiv02B Speci03A Speci03B 

預期的數據集:

ID1: Indiv01 Indiv01 Indiv02 Indiv02 Speci03 Speci03 
ID2: A B A B A B 

我已經通過對分割數據的其他職位看,但他們似乎都不得不分開列名(一種獨特的方式即:用逗號分隔兩個組件,或一段時間)。

這是我想會的工作最好的代碼,但我無法弄清楚如何爲「7個字符」作爲分割點代碼,而不是一個逗號:

sapply(strsplit(as.character(d$ID), ",")

任何幫助,將不勝感激。

回答

7

下面是與strsplit解決方案的正則表達式。它分裂的第7和第8個字符的字符串:

ID1 <- c("Indiv01A", "Indiv01B", "Indiv02A", "Indiv02B", "Speci03A", "Speci03B") 

res <- strsplit(ID1, "(?<=.{7})", perl = TRUE) 

# [[1]] 
# [1] "Indiv01" "A"  
# 
# [[2]] 
# [1] "Indiv01" "B"  
# 
# [[3]] 
# [1] "Indiv02" "A"  
# 
# [[4]] 
# [1] "Indiv02" "B"  
# 
# [[5]] 
# [1] "Speci03" "A"  
# 
# [[6]] 
# [1] "Speci03" "B" 

現在,你可以使用rbind創建兩列:

do.call(rbind, res) 
#  [,1]  [,2] 
# [1,] "Indiv01" "A" 
# [2,] "Indiv01" "B" 
# [3,] "Indiv02" "A" 
# [4,] "Indiv02" "B" 
# [5,] "Speci03" "A" 
# [6,] "Speci03" "B" 

的正則表達式的說明:

(?<=.{7}) 

(?<=)是一個(正面)向後看。它匹配指定模式之前的任何位置。這裏的模式是.{7}。點(.)匹配任何字符。 {7}意味着7次。因此,正則表達式匹配前面恰好有7個字符的位置。

+0

+1比我的產品更優雅。你介意解釋你的模式嗎? – jbaums

+0

@jbaums我添加了一個解釋。 –

+0

這是一個很好的解釋和易於理解!我唯一的困難是,我仍然被卡住,試圖將它應用到我的列標題或data.frame中的第一行。有什麼想法嗎?謝謝! – KKL234

1

有幾種方法可以解決這個問題。

要提取的最後一個字符

首先,substr

new.vec <- sapply(old.vec, function(x) substr(x, nchar(x), nchar(x))) 

,或者與sub

new.vec <- sub('.*(.)', '\\1', old.vec) 

其中old.vec是要串的矢量分裂。

對於興趣,後者選項使用regular expression其轉換爲:「捕獲跟隨零個或多個其他字符的單個字符(.)(.*)(通過用括號包圍表示),並與所捕獲的內容替換匹配(\\1)「。有關更多信息,請參見?gsubhere

上述選項允許改變字符串長度。但是,如果你做總是想後7個字符分割,字符串的第二部分總是有隻是一個單一的字符,那麼下面應該工作:

new.vec <- substr(old.vec, 8, 8) 

(編輯,包括方法提取字符串的第一部分。)

提取所有最後一個字符

這個過程是相似的。

new.vec <- sapply(old.vec, function(x) substr(x, 1, nchar(x) - 1)) 

new.vec <- sub('(.*).', '\\1', old.vec) 

new.vec <- substr(old.vec, 1, 7) 
+0

感謝您的快速響應!我已經嘗試了選項1和3,並且由於試圖指示要更改哪一行,我遇到了困難。數據集中的第一行(「年」)包含各個ID。我已經嘗試了下面的代碼,輸出如下。 FK1split [1]「1」「1」「2」「2」 「2」「2」「2」「2」「2」「2」「2」「2」「2」「2」 > FK1split < - substr(FK1 $ Year,8,8) > FK1split [ 1]「」「」「」「」「」「」「」「」「」「」「」「」「」「」「」「」「」「」「」有關如何輕鬆指示data.frame的哪一行應該被拆分的想法? – KKL234

+0

不要在第一個版本中將'x'更改爲'7'和'1' - 您的更改只是提取'FK1 $ Year'每個元素的第一個字符。另外,要明白'substr(FK1 $ Year,8,8)'是爲了提取'FK1 $ Year'每個元素的第8到第8(即只是第8個)字符。它看起來像'FK1 $ Year'可能沒有8個字符。相應地調整「8」和「8」(它們指示開始和結束提取的位置)。順便說一句,用反引號括起代碼(通常在'〜'鍵上)來格式化註釋中的代碼。 – jbaums

2

這裏是一個gsubfn解決方案:

library(gsubfn) 

strapplyc(ID1, "(.*)(.)", simplify = cbind) 

這給出了這樣的矩陣:

 [,1]  [,2]  [,3]  [,4]  [,5]  [,6]  
[1,] "Indiv01" "Indiv01" "Indiv02" "Indiv02" "Speci03" "Speci03" 
[2,] "A"  "B"  "A"  "B"  "A"  "B"  

,或者如果你想兩列(而不是兩行)代替cbind使用rbind

+0

感謝您突出顯示此軟件包 - 以前沒有遇到過! – jbaums