2016-02-05 7 views
6

मैं तय कर दी है चौड़ाई डेटा फ़ाइलों (.dbf) पंक्ति विभाजक की जरूरत नहीं है कि के साथ निश्चित चौड़ाई डेटा फ़ाइल। यहाँ कि datafile की दो पंक्तियाँ दिखता है की तरह है:आयात कोई लाइन विभाजक

20141101 77h 3.210         0 3 20141102 76h 3.090         0 3 

एक लाइन की चौड़ाई तारीख के लिए c(8,4,7,41) (8), कुछ समय के उपाय है (4), डेटा बिंदु (7), और कुछ अन्य स्तंभों को मैं एक "आराम" कॉलम (41) में सारांशित कर सकता हूं। एक पंक्ति के बाद कोई विभाजक नहीं है और अगली पंक्ति सिर्फ पहली पंक्ति में संलग्न है। सभी समय कदम मूल रूप से एक विशाल रेखा में लगातार लिखे जाते हैं। इस फ़ाइल में विशेष रूप से संख्याएं, वर्ण और सफेद स्थान है।

साथ read.fwf('filepath', widths = c(8,4,7,41)) आर बंद हो जाता है लाइन विभाजक की कमी के कारण पहली पंक्ति के बाद पढ़ने।

वहाँ बताने के लिए read.fwf() जब नई लाइन पढ़ने जब कोई लाइन विभाजक शुरू करने के लिए एक तर्क है? या मैं एक अलग पढ़ने के आदेश का उपयोग करना चाहिए?

अग्रिम धन्यवाद।

+3

आप प्रत्येक 60 चार नंबर में लाइन विभाजक जोड़ सकते हैं? ([Sed के साथ उदाहरण] (http://stackoverflow.com/questions/1187078/how-to-insert-a-new-line-character-after-a-fixed-number-of-characters-in-a-file)) – Tensibai

उत्तर

3

एक अलग है, और शायद कम सुंदर,साथ समाधान 0, substr, trimws, separate ( tidyr) और mutate_all (dplyr):

txt <- readLines('filepath') 
dfx <- data.frame(V1 = sapply(seq(from=1, to=nchar(txt), by=60), 
           function(x) substr(txt, x, x+59))) 

library(dplyr) 
library(tidyr) 
dfx %>% 
    separate(V1, c(paste0("V",LETTERS[1:5])), c(8,12,19,55)) %>% 
    mutate_all(trimws) 

जो देता है:

 VA VB VC VD VE 
1 20141101 77h 3.210 0 3 
2 20141102 76h 3.090 0 3 

अलग स्तंभ नाम के लिए, बस का एक वेक्टर के साथ c(paste0("V",LETTERS[1:5]) की जगह कॉलमनाम जो आप चाहते हैं।

यदि आप character में कॉलम को सही कक्षाओं में बदलना चाहते हैं, तो आप mutate_all के अंदर उपयोग कर सकते हैं।

+0

स्वच्छ और सही समाधान। धन्यवाद! – Ben

+0

@ बेन थेंक्स :-) अब कॉलम कक्षाओं को सही करने के बारे में भी एक नोट जोड़ा गया। – Jaap

4
नहीं

हो सकता है कि सबसे अच्छा विचार है, लेकिन यह काम करना चाहिए:

content <- scan('filepath','character',sep='~') # Warning choose a sep not appearing in datas to get the whole file. 
# Split content in lines: 
lines <- regmatches(content,gregexpr('.{60}',content))[[1]] 
x <- tempfile() 
write(lines,x) 
data <- read.fwf(x, widths = c(8,4,7,41)) 
unlink(x) 

विचार, पूरे फ़ाइल को पढ़ने को एक प्रविष्टि में 60 वर्ण की प्रत्येक क्रिया प्राप्त एक tempfile को यह लिखते हैं, और पढ़ने के लिए है अस्थायी फ़ाइल को हटाने से पहले इस tempfile से डेटा।

एक और दृष्टिकोण regexes के साथ संभव है और (ऊपर स्कैन से उत्पन्न सामग्री के साथ अभी भी) stringr पैकेज: जो देता है

library(stringr) 
d <- data.frame(str_match_all(content, "(.{8})(.{4})(.{7})(.{41})")[[1]][,2:5], stringsAsFactors=FALSE) 

:

 V1 V2  V3          V4 
1 20141101 77h 3.210         0 3 
2 20141102 76h 3.090         0 3 

str_match_all वापसी एक सूची है, यहाँ 1 तत्व क्योंकि साथ वहाँ इनपुट के रूप में केवल एक लाइन है, इसलिए हम [[1]] साथ उसे निकाल दें।

अब वापसी 5 कॉलम, पहले एक पूर्ण मैच किया जा रहा है, दूसरों को किया जा रहा है कैप्चर समूहों तो हम 2 से 5 स्तंभों पर मैट्रिक्स सबसेट केवल 4 स्तंभों हम की जरूरत हो और as.data.frame में लपेट एक पाने के लिए करने के लिए है अंत में डेटा.फ्रेम।

आप तो इस तरह के साथ colnames(d) <- c('date','time','data_point','rest')

आप सफेद रिक्त स्थान को साफ करना चाहते हैं तो आप में trimws str_extract_all परिणाम लपेट (धन्यवाद इस समारोह की याद के लिए @jaap करने के लिए) कर सकते हैं कॉलम नाम कर सकते हैं:

td <- data.frame(trimws(str_match_all(content, "(.{8})(.{4})(.{7})(.{41})")[[1]][,2:5]), stringsAsFactors=FALSE) 

आउटपुट:

 X1 X2 X3  X4 
1 20141101 77h 3.210 0 3 
2 20141102 76h 3.090 0 3 
+1

सुझाव के लिए बहुत बहुत धन्यवाद, लेकिन इस समाधान के साथ एक ही समस्या है, read.fwf() पहली पंक्ति के बाद बंद हो जाता है। – Ben

+0

@ वास्तव में, मुझे इसका परीक्षण करना चाहिए था। मैं एक उचित समाधान के साथ जवाब अद्यतन कर दूंगा। – Tensibai

+0

@ तेंसबाई इसमें बहुत समय नहीं लगाते क्योंकि जैप का जवाब अच्छी तरह से काम करता है। लेकिन आपकी सलाह के लिए धन्यवाद! – Ben

0

अन्य उत्तर के अलावा, कुछ सामान्य जानकारी dbf files के बारे में:

जब तक यह एक बार स्थिर फ़ाइल का पढ़ा है, यह सबसे अच्छा होगा पहले उस पर बदल जाता है के मामले में फ़ाइल/क्षेत्रों संरचना की जाँच करने के लिए पहर। एक डीबीएफ फ़ाइल की आंतरिक संरचना के लिए here देखें।

लेकिन शायद और भी अधिक महत्वपूर्ण:

में DBF फ़ाइल में प्रत्येक रिकॉर्ड नष्ट झंडा के लिए एक बाइट से पहले किया गया है। यदि यह एक स्थान है, तो रिकॉर्ड हटाया नहीं गया है, अगर यह तारांकन * रिकॉर्ड को हटाने के लिए चिह्नित किया गया है (रिकॉर्ड को तब तक नहीं हटाया जाता है जब तक फ़ाइल पैक) नहीं है, और आप शायद उन रिकॉर्ड्स को छोड़ना चाहते हैं। उदाहरण के लिए डेटा का पहला भाग "DELETED" के साथ ओवरराइट किया जा सकता है।

तो, अपने रिकॉर्ड c(8,4,7,41) में, बाकी स्तंभ (41) के अंतिम बाइट वास्तव में रिकॉर्ड है कि यह इस प्रकार की हटाने झंडा है - और फ़ाइल में पिछले रिकॉर्ड ही नहीं क्षेत्र के लिए 40 बाइट्स होगा (लेकिन यदि आप भाग्यशाली हैं, तो फ़ाइल में एक ईओएफ मार्कर (0x1a) है, इसलिए हो सकता है कि आपको वहां आकार के साथ कोई समस्या न हो)।

इस प्रकार, आपका रिकॉर्ड वास्तव में होना चाहिए: c(1,8,4,7,40), जहां 1 डिलीट ध्वज है, और जल्द ही एक बाइट शुरू कर रहा है।

+0

बहुत उपयोगी जानकारी, धन्यवाद! – Ben

संबंधित मुद्दे