[英]Efficient replacement for for-loop when splitting strings in R
我有一個大型數據框(20列,> 100k行),需要將一列字符串拆分成多個新列。
有關列的前3個觀察結果如下:
scans <- data.frame(scan = c("CT Cervical Sp,CT Head Plain", "II < 1 Hour",
"L-S Spine,L-S Spine"))
看起來像這樣:
scan
1 CT Cervical Sp,CT Head Plain
2 II < 1 Hour
3 L-S Spine,L-S Spine
我需要將其拆分為5列(每個觀察中最多有5個子串),對於具有較少子串的觀察,我希望剩余的列填充有NA。 我目前正在使用此代碼:
scans <- data.frame(scan = c("CT Cervical Sp,CT Head Plain", "II < 1 Hour",
"L-S Spine,L-S Spine"))
for(i in 1:nrow(scans)){
scans$scan1[i] <- strsplit(scans$scan, ",")[[i]][1]
scans$scan2[i] <- strsplit(scans$scan, ",")[[i]][2]
scans$scan3[i] <- strsplit(scans$scan, ",")[[i]][3]
scans$scan4[i] <- strsplit(scans$scan, ",")[[i]][4]
scans$scan5[i] <- strsplit(scans$scan, ",")[[i]][5]
}
它工作並輸出我想要的解決方案:
scan scan1 scan2 scan3 scan4 scan5
1 CT Cervical Sp,CT Head Plain CT Cervical Sp CT Head Plain NA NA NA
2 II < 1 Hour II < 1 Hour NA NA NA NA
3 L-S Spine,L-S Spine L-S Spine L-S Spine NA NA NA
......但它確實很慢。 循環數十或數十萬次觀測是耗時的。
非常感謝任何建議。
另一種方法是使用tstrsplit
的開發人員版本的data.table
library(data.table) # v >= 1.9.5
setDT(scans)[, tstrsplit(scan, ",", fixed = TRUE)]
# V1 V2
# 1: CT Cervical Sp CT Head Plain
# 2: II < 1 Hour NA
# 3: L-S Spine L-S Spine
如果您確定至少有5次拆分,則可以通過引用輕松創建這些列
setDT(scans)[, paste0("scan", 1:5) := tstrsplit(scan, ",")]
或者, tidyr
包提供類似的functuanality
library(tidyr)
separate(scans, scan, paste0("scan", 1:2), ",", extra = "merge", remove = FALSE)
# scan scan1 scan2
# 1 CT Cervical Sp,CT Head Plain CT Cervical Sp CT Head Plain
# 2 II < 1 Hour II < 1 Hour <NA>
# 3 L-S Spine,L-S Spine L-S Spine L-S Spine
或者僅使用base R
另一種選擇
cbind(scans, read.table(text= as.character(scans$scan),sep=",", fill=TRUE, na.strings=''))
您可以使用:
library(splitstackshape)
cSplit(scans, colnames(scans), sep=',')
# scan_1 scan_2
#1: CT Cervical Sp CT Head Plain
#2: II < 1 Hour NA
#3: L-S Spine L-S Spine
請注意返回的對象是data.table
。 如果需要,您可以轉換為data.frame
。 這里只有兩列,因為數據中最多只有一個逗號。 如果將其應用於帶有4個逗號的某些單元格的數據,您將獲得所需的輸出。
使用驚人的stringi
包 - 我挑戰任何人找到更快的解決方案。
# this does all the work
result <- as.data.frame(stringi::stri_split_fixed(scans$scan, ",", simplify = TRUE))
這將填充與逗號分隔符一樣多的列。
要從問題中獲得准確的結果,請重命名列並將空字符串轉換為NA
:
# rename the columns if you wish
names(result) <- paste0("scan", 1:ncol(result))
# replace "" with NA
result[result==""] <- NA
cbind(scans, result)
## scan scan1 scan2
## 1 CT Cervical Sp,CT Head Plain CT Cervical Sp CT Head Plain
## 2 II < 1 Hour II < 1 Hour <NA>
## 3 L-S Spine,L-S Spine L-S Spine L-S Spine
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.