2017-01-28 5 views
5

मैं एक पाठ फ़ाइल जो लगता है कि में डेटा दिया गया था:आर में खराब संरचना डेटा आयात करने

var1, var2, var3, iteration, data, 
    0, -5, 1.8,   0, 1.203, 
    0, -5, 1.8,   1, 1.206, 
    ... 
    10, -5, 1.8,   0, 1.203, 

:

Measurement: mc 
Loop: 
var1=0, var2=-5, var3=1.8 
values: 
iteration  data 
0    1.203 
1    1.206 
2    2.206 
3    1.201 
4    1.204 
5    1.204 
6    1.204 
statistics: 
max   1.206 
min   1.201 
mean   1.204 
stddev  0.001 
avgdev  0.001 
failedtimes 0 

Measurement: mc 
Loop: 
var1=10, var2=-5, var3=1.8 
values: 
iteration  data 
0    1.203 
1    1.206 
2    2.206 
3    1.201 
statistics: 
max   1.206 
min   1.201 
mean   1.204 
stddev  0.001 
avgdev  0.001 
failedtimes 0 

मैं की तरह एक अधिक सामान्य प्रारूप में डेटा प्राप्त करने के लिए देख रहा हूँ मुझे इस तरह के डेटा को पार्स करने की कोशिश करने में समस्याएं आ रही हैं। pls मदद

+0

आप 'का उपयोग कर read.table' के' skip' और 'nrows' तर्क' iteration' और 'डेटा' स्तंभों पर कब्जा करने की कोशिश की है? – adatum

+0

ओह, और यदि यह एक निश्चित चौड़ाई स्वरूपित फ़ाइल है, तो इसके लिए 'read.fwf' है। – adatum

उत्तर

6

प्रासंगिक तरीकों को खींचने के लिए सरल regex और readLines का उपयोग करने का एक तरीका है।

आपका डाटा

txt <- 
    "Measurement: mc 
Loop: 
var1=0, var2=-5, var3=1.8 
values: 
iteration  data 
0    1.203 
1    1.206 
2    2.206 
3    1.201 
4    1.204 
5    1.204 
6    1.204 
statistics: 
max   1.206 
min   1.201 
mean   1.204 
stddev  0.001 
avgdev  0.001 
failedtimes 0 

Measurement: mc 
Loop: 
var1=10, var2=-5, var3=1.8 
values: 
iteration  data 
0    1.203 
1    1.206 
2    2.206 
3    1.201 
statistics: 
max   1.206 
min   1.201 
mean   1.204 
stddev  0.001 
avgdev  0.001" 


# Read in : you can pass the file path instead of textConnection 
r = readLines(textConnection(txt)) 

# Find indices of relevant parts of string that you want to keep 
id1 = grep("var", r) 
id2 = grep("iteration", r) 
id3 = grep("statistics", r) 

# indices for iteration data 
m = mapply(seq, id2, id3-1) 

# Use read.table to parse the relevant rows 
lst <- lapply(seq_along(m), function(x) 
        cbind(read.table(text=r[id1][x], sep=","), #var data 
          read.table(text=r[m[[x]]], header=TRUE))) # iteration data 

dat <- do.call(rbind, lst) 

# Remove the var= text and convert to numeric 
dat[] <- lapply(dat, function(x) as.numeric(gsub("var\\d+=", "", x))) 
dat 
# V1 V2 V3 iteration data 
# 1 0 -5 1.8   0 1.203 
# 2 0 -5 1.8   1 1.206 
# 3 0 -5 1.8   2 2.206 
# 4 0 -5 1.8   3 1.201 
# 5 0 -5 1.8   4 1.204 
# 6 0 -5 1.8   5 1.204 
# 7 0 -5 1.8   6 1.204 
# 8 10 -5 1.8   0 1.203 
# 9 10 -5 1.8   1 1.206 
# 10 10 -5 1.8   2 2.206 
# 11 10 -5 1.8   3 1.201 

वास्तव में अनुभागों में डेटा को विभाजित और फिर यानी एक समारोह लागू करने के लिए एक सा साफ हो सकता है

sp <- split(r, cumsum(grepl("measure", r, TRUE))) 

# Function to parse 
fun <- function(x){ 
    id1 = grep("var", x) 
    id2 = grep("iteration", x) 
    id3 = grep("statistics", x) 
    m = seq(id2, id3-1) 

    cbind(read.table(text=x[id1], sep=","), 
      read.table(text=x[m], header=TRUE)) 
} 

lst <- lapply(sp, fun) 

फिर conti

+0

आपका पहला जवाब अच्छी तरह से काम करता था, सिवाय इसके कि मुझे 'mapply()' के बजाय 'मानचित्र() 'का उपयोग करना था, यह सुनिश्चित नहीं है कि क्यों' mapply()' सूची को आउटपुट नहीं कर रहा था? – verigolfer

+0

@verigolfer; मैपली ने इस उदाहरण में (इंडेक्स की सूची बनाने में) काम किया क्योंकि प्रत्येक पुनरावृत्ति के सूचकांक एक अलग लंबाई के थे। यदि आपका डेटा एक ही प्रारूप है, तो मुझे लगता है कि यह सच होगा, लेकिन 'mapply' या' Map' – user20650

3

जैसा कि एक पाइपलाइन है जो इसे पढ़ता है और इसे संसाधित करता है। अंत में नोट के अनुसार डेटा L में मान लें। आपको इसे L <- readLines("myfile.dat") जैसे कुछ बनाने की आवश्यकता होगी।

trimws का उपयोग करके अग्रणी और पिछली सफेद जगह का ट्रिम करें - इस चरण की आवश्यकता नहीं हो सकती है, लेकिन अगर डेटा की रेखाओं की शुरुआत में डेटा व्हाइटस्पेस हो तो यह चोट नहीं पहुंचा सकता है। फिर grep लाइनों से शुरू होने वाली रेखाओं में varv, a, r, = को एक स्थान के साथ बदलकर और कोमा को एक नई लाइन के साथ बदलना। यह इसे इस रूप में रखता है कि read.table इसे 2 कॉलम डेटा फ्रेम में पढ़ सकता है जिसमें पहला कॉलम 1, 2, 3 है, इसके बाद पुनरावृत्ति संख्या और दूसरा कॉलम var1, var2, var3 और data सभी का मान है प्रत्येक समूह के लिए दोहराया। हम अभिव्यक्ति cumsum(...) %/% 2 अभिव्यक्ति का उपयोग करके क्रमिक रनों की पहचान करके समूहबद्ध चर बनाते हैं। यह मानता है कि प्रति समूह कम से कम 2 पुनरावृत्तियों (0 और 1) हैं। (दिखाए गए आंकड़ों से यह एपर्स है कि यह मामला है, लेकिन यदि नहीं, तो इसे बाद में दिखाए गए अतिरिक्त कोड के साथ संबोधित किया जा सकता है।) अंत में, समूह अभिव्यक्ति द्वारा विभाजित किया गया है और प्रत्येक ऐसे विभाजित समूह को आवश्यक डेटा फ्रेम में पुन: कार्य करना है।

library(purrr) 

L %>% 
    trimws %>% 
    grep(pattern = "^\\d|var", value = TRUE) %>% 
    chartr(old = "var=,", new = " \n") %>% 
    read.table(text = .) %>% 
    split(cumsum(c(FALSE, diff(.$V1) != 1)) %/% 2) %>% 
    map_df(function(x) data.frame(var1 = x[1, 2], var2 = x[2, 2], 
     var3 = x[3, 2],iteration = x[-(1:3), 1], data = x[-(1:3), 2])) 

दे रही है:

var1 var2 var3 iteration data 
1  0 -5 1.8   0 1.203 
2  0 -5 1.8   1 1.206 
3  0 -5 1.8   2 2.206 
4  0 -5 1.8   3 1.201 
5  0 -5 1.8   4 1.204 
6  0 -5 1.8   5 1.204 
7  0 -5 1.8   6 1.204 
8 10 -5 1.8   0 1.203 
9 10 -5 1.8   1 1.206 
10 10 -5 1.8   2 2.206 
11 10 -5 1.8   3 1.201 

भिन्नता कोड की यह विविधता मामले में जहां केवल एक यात्रा है संभालती है, यानी यात्रा 0, और कुछ की कीमत पर समूहीकरण गणना को सरल कोड की अधिक लाइनें। यहां 99 99 के दो उदाहरण हो सकते हैं जो डेटा में प्रकट नहीं होते हैं।

L %>% 
    grep(pattern = "^\\s*\\d|var", value = TRUE) %>% 
    sub(pattern = "var", replacement = "-9999 var") %>% 
    gsub(pattern = "[^0-9.,-]", replacement = " ") %>% 
    gsub(pattern = ",", replacement = "\n") %>% 
    strsplit("\\s+") %>% 
    unlist %>% 
    as.numeric %>% 
    split(cumsum(. == -9999)) %>% 
    map_df(function(x) { 
    x <- t(matrix(x[-1], 2)) 
    data.frame(var1 = x[1, 2], var2 = x[2, 2], var3 = x[3, 2], 
     iteration = x[-(1:3), 1], data = x[-(1:3), 2]) 
    }) 

dplyr/tidyr हम बारी-बारी से dplyr और tidyr संकुल इस्तेमाल कर सकते हैं।vars में 3 कॉलम var1, var2 और var3 और प्रति समूह एक पंक्ति है। values में एक कॉलम है जिसमें पुनरावृत्ति और डेटा के नेस्टेड दो कॉलम डेटा फ्रेम होते हैं और प्रति समूह एक पंक्ति होती है लेकिन प्रत्येक ऐसी पंक्ति में कई पंक्तियों का डेटा फ्रेम होता है।

library(tidyr) 
library(dplyr) 

vars <- L %>% 
    grep(pattern = "var", value = TRUE) %>% 
    gsub(pattern = "[=,]", replacement = " ") %>% 
    read.table(text = ., col.names = c(NA, "var1", NA, "var2", NA, "var3")) %>% 
    select(var1, var2, var3) 

values <- L %>% 
    trimws %>% 
    grep(pattern = "^\\d", value = TRUE) %>% 
    read.table(text = ., col.names = c("iteration", "data")) %>% 
    mutate(g = cumsum(iteration == 0)) %>% 
    nest(-g) %>% 
    select(-g) 


cbind(vars, values) %>% unnest 

नोट:

Lines <- "Measurement: mc 
Loop: 
var1=0, var2=-5, var3=1.8 
values: 
iteration  data 
0    1.203 
1    1.206 
2    2.206 
3    1.201 
4    1.204 
5    1.204 
6    1.204 
statistics: 
max   1.206 
min   1.201 
mean   1.204 
stddev  0.001 
avgdev  0.001 
failedtimes 0 

Measurement: mc 
Loop: 
var1=10, var2=-5, var3=1.8 
values: 
iteration  data 
0    1.203 
1    1.206 
2    2.206 
3    1.201 
statistics: 
max   1.206 
min   1.201 
mean   1.204 
stddev  0.001 
avgdev  0.001 
failedtimes 0" 
L <- readLines(textConnection(Lines)) 
+0

में 'सरल = गलत' का उपयोग करके स्पष्ट रूप से स्पष्ट होना बेहतर है। धन्यवाद। मुझे इस '%>%' ऑपरेटर में दिलचस्पी है। ऐसा लगता है कि आप एक पाइप के रूप में उपयोग कर रहे हैं। ऐसा लगता है कि आर में कुछ नई शैलियों पिछले कुछ वर्षों में दिखाई दी है। – verigolfer

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