एक data.table कॉलम में टेक्स्ट स्ट्रिंग को विभाजित करें


86

मेरे पास एक स्क्रिप्ट है जो सीएसवी फ़ाइल से डेटा को एक में पढ़ता है data.tableऔर फिर एक कॉलम में कई नए कॉलमों में पाठ को विभाजित करता है। मैं वर्तमान में ऐसा करने के लिए lapplyऔर strsplitकार्यों का उपयोग कर रहा हूं । यहाँ एक उदाहरण है:

library("data.table")
df = data.table(PREFIX = c("A_B","A_C","A_D","B_A","B_C","B_D"),
                VALUE  = 1:6)
dt = as.data.table(df)

# split PREFIX into new columns
dt$PX = as.character(lapply(strsplit(as.character(dt$PREFIX), split="_"), "[", 1))
dt$PY = as.character(lapply(strsplit(as.character(dt$PREFIX), split="_"), "[", 2))

dt 
#    PREFIX VALUE PX PY
# 1:    A_B     1  A  B
# 2:    A_C     2  A  C
# 3:    A_D     3  A  D
# 4:    B_A     4  B  A
# 5:    B_C     5  B  C
# 6:    B_D     6  B  D 

कॉलम के ऊपर के उदाहरण PREFIXमें दो नए कॉलम PXऔर PY"_" वर्ण पर विभाजित किया गया है ।

हालांकि यह ठीक काम करता है, मैं सोच रहा था कि क्या इस का उपयोग करने के लिए एक बेहतर (अधिक कुशल) तरीका है data.table। मेरे असली डेटासेट में> = 10M + पंक्तियाँ हैं, इसलिए समय / मेमोरी दक्षता वास्तव में महत्वपूर्ण हो जाती है।


अपडेट करें:

@ फ्रैंक के सुझाव के बाद मैंने एक बड़ा परीक्षण मामला बनाया और सुझाए गए आदेशों का उपयोग किया, लेकिन stringr::str_split_fixedमूल विधि की तुलना में बहुत अधिक समय लगता है।

library("data.table")
library("stringr")
system.time ({
    df = data.table(PREFIX = rep(c("A_B","A_C","A_D","B_A","B_C","B_D"), 1000000),
                    VALUE  = rep(1:6, 1000000))
    dt = data.table(df)
})
#   user  system elapsed 
#  0.682   0.075   0.758 

system.time({ dt[, c("PX","PY") := data.table(str_split_fixed(PREFIX,"_",2))] })
#    user  system elapsed 
# 738.283   3.103 741.674 

rm(dt)
system.time ( {
    df = data.table(PREFIX = rep(c("A_B","A_C","A_D","B_A","B_C","B_D"), 1000000),
                     VALUE = rep(1:6, 1000000) )
    dt = as.data.table(df)
})
#    user  system elapsed 
#   0.123   0.000   0.123 

# split PREFIX into new columns
system.time ({
    dt$PX = as.character(lapply(strsplit(as.character(dt$PREFIX), split="_"), "[", 1))
    dt$PY = as.character(lapply(strsplit(as.character(dt$PREFIX), split="_"), "[", 2))
})
#    user  system elapsed 
#  33.185   0.000  33.191 

इसलिए इस str_split_fixedविधि में लगभग 20 गुना अधिक समय लगता है।


मुझे लगता है कि data.table के बाहर ऑपरेशन करना सबसे पहले बेहतर हो सकता है। यदि आप stringrपैकेज का उपयोग करते हैं , तो यह कमांड है str_split_fixed(PREFIX,"_",2):। मैं जवाब नहीं दे रहा हूं क्योंकि मैंने स्पीडअप का परीक्षण नहीं किया है ... या, एक चरण में:dt[,c("PX","PY"):=data.table(str_split_fixed(PREFIX,"_",2))]
फ्रैंक

जवाबों:


122

अपडेट: संस्करण 1.9.6 (सेप 15 के रूप में सीआरएएन) से, हम tstrsplit()सीधे परिणाम प्राप्त करने के लिए फ़ंक्शन का उपयोग कर सकते हैं (और बहुत अधिक कुशल तरीके से):

require(data.table) ## v1.9.6+
dt[, c("PX", "PY") := tstrsplit(PREFIX, "_", fixed=TRUE)]
#    PREFIX VALUE PX PY
# 1:    A_B     1  A  B
# 2:    A_C     2  A  C
# 3:    A_D     3  A  D
# 4:    B_A     4  B  A
# 5:    B_C     5  B  C
# 6:    B_D     6  B  D

tstrsplit()मूल रूप से एक रैपर है transpose(strsplit()), जहां transpose()फ़ंक्शन, हाल ही में लागू किया गया है, एक सूची स्थानांतरित करता है। कृपया देखें ?tstrsplit()और ?transpose()उदाहरण के लिए।

पुराने उत्तरों के लिए इतिहास देखें।


धन्यवाद अरुण मैंने पहले सूची बनाने की विधि के बारे में नहीं सोचा था, फिर सूचकांक और फिर "a_spl" में वर्णित कॉलम। मैंने हमेशा सोचा था कि एक ही लाइन में सब कुछ करना सबसे अच्छा तरीका था। बस जिज्ञासा से बाहर क्यों सूचकांक रास्ता इतनी तेजी से काम करता है?
डेरिक लुईस

@ अरुण, इस सवाल से संबंधित, आप किसी फंक्शन में क्या देखेंगे जैसे मैंने यहां लिखा है: gist.github.com/mrdwab/6873058 मूल रूप से, मैंने इसका उपयोग किया है fread, लेकिन ऐसा करने के लिए, मुझे एक का उपयोग करना था tempfile(जो ऐसा लगता है कि यह एक अड़चन होगी) क्योंकि ऐसा नहीं लगता है कि freadयह एक textतर्क के बराबर है । इस नमूना डेटा के साथ परीक्षण, इसका प्रदर्शन आपके a_splऔर a_subदृष्टिकोणों के बीच है ।
a5C1D2H2I1M1N2O1R2T1

4
मैं सोच रहा था कि कोई कैसे LHS पर स्तंभों की संख्या का अनुमान लगा सकता है: = और गतिशील रूप से grep tstrsplit घटनाओं के आधार पर नए स्तंभों के नाम बनाते हैं
amank

15

मैं किसी ऐसे व्यक्ति के लिए उत्तर जोड़ता हूं जो data.table v1.9.5 का उपयोग नहीं करता है और एक लाइन समाधान भी चाहता है।

dt[, c('PX','PY') := do.call(Map, c(f = c, strsplit(PREFIX, '-'))) ]

7

splitstackshapeपैकेज का उपयोग :

library(splitstackshape)
cSplit(df, splitCols = "PREFIX", sep = "_", direction = "wide", drop = FALSE)
#    PREFIX VALUE PREFIX_1 PREFIX_2
# 1:    A_B     1        A        B
# 2:    A_C     2        A        C
# 3:    A_D     3        A        D
# 4:    B_A     4        B        A
# 5:    B_C     5        B        C
# 6:    B_D     6        B        D

4

हम प्रयास कर सकते हैं:

cbind(dt, fread(text = dt$PREFIX, sep = "_", header = FALSE))
#    PREFIX VALUE V1 V2
# 1:    A_B     1  A  B
# 2:    A_C     2  A  C
# 3:    A_D     3  A  D
# 4:    B_A     4  B  A
# 5:    B_C     5  B  C
# 6:    B_D     6  B  D

1

समाधान के साथ समाधान है:

separate(df,col = "PREFIX",into = c("PX", "PY"), sep = "_")

विशेष रूप से data.table समाधान के लिए पूछा गया प्रश्न। इस डोमेन में काम करने वाले लोगों ने अपनी चुनौतियों के सापेक्ष अच्छे कारण के लिए डेटा समाधानों को प्राथमिकता में पहले से ही डेटाटेबल समाधान चुना है।
माइकल टचमैन

अन्य उपयोगकर्ताओं ने अन्य पुस्तकालयों के साथ भी समाधान प्रदान किया है, मैंने अभी एक वैध विकल्प दिया है, आसान और तेज।
स्कान
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.