2014-11-30 10 views
11

Birisi bazı örnek olarak konsol çıktısı gönderdi. (Bu çok şey oluyor ve vektörler ve veri çerçeveleri için çıktı çıktılarını dönüştürmek için stratejilerim var.) Bunu gerçek bir R listesine ayrıştırmak için şık bir yöntemin olup olmadığını merak ediyorum. Listenin konsol çıktısını gerçek bir R listesine dönüştürün

test <- "[[1]] 
[1] 1.0000 1.9643 4.5957 

[[2]] 
[1] 1.0000 2.2753 3.8589 

[[3]] 
[1] 1.0000 2.9781 4.5651 

[[4]] 
[1] 1.0000 2.9320 3.5519 

[[5]] 
[1] 1.0000 3.5772 2.8560 

[[6]] 
[1] 1.0000 4.0150 3.1937 

[[7]] 
[1] 1.0000 3.3814 3.4291" 

Bu

adlı ve un-adlandırılmış düğümlerle bir örnektir: Ben str listelerini nasıl işleyeceğini kod aracılığıyla çalıştık

L <- 
structure(list(a = structure(list(d = 1:2, j = 5:6, o = structure(list(
    w = 2, 4), .Names = c("w", ""))), .Names = c("d", "j", "o" 
)), b = "c", c = 3:4), .Names = c("a", "b", "c")) 

> L 
$a 
$a$d 
[1] 1 2 

$a$j 
[1] 5 6 

$a$o 
$a$o$w 
[1] 2 

$a$o[[2]] 
[1] 4 



$b 
[1] "c" 

$c 
[1] 3 4 

, ama aslında ters dönüşüm yapıyor. Bunun, bu mantık gibi bir şeye yinelenen bir çağrı olacak bu satırlar boyunca bir şekilde yapılandırılması gerektiğine inanıyorum, çünkü listeler (son indeksten önceki "$" olacaktır) veya adsız olarak adlandırılabilir (bu durumda) içine bir dizi olacak

parseTxt <- function(Lobj) { 
    #setup logic 
# Untested code... basically a structure to be filled in 
rdLn <- function(Ln) { 
    for(ln in length(inp)) { 
     m <- gregexpr("\\[\\[|\\$", "$a$o[[2]]") 
     separators <- regmatches("$a$o[[2]]", m) 
     curr.nm=NA 
     if (tail(separators, 1) == "$"){ 
        nm <- sub("^.+\\$","",ln) 
        if(!nm %in% curr.nm){ curr.nm <-c(nm, curr.nm) } 
     } else { if (tail(separators, 1) == '[['){ 
      # here need to handle "[[n]]" case 
     } else { and here handle the "[n]" case 
        } 
    } 
} 
+5

Cidden, 'dput' çıktısını isteyin. Eğer bunu sağlamazlarsa, reddetmek ve devam etmek. * * * Lapply (readLines (textConnection (gsub ("\ n (? = \ N) | \\ [\\ [\\ d * \\] \\] \ n | \\ [\ gibi bir canavarlığı kullanabilirsiniz \ d * \\] "," ", test, perl = TRUE))), işlev (x) tarama (textConnection (x))), ama yapmazdım. – Roland

+0

Roland'a katılıyorum. Alternatif canavarlık 'read.delim'dir (text = gsub (" \\ [+ \\ d + \\] + "," ", test), header = FALSE, sep =" ")' dır ancak sadece bu durum için çalışır. – Andrie

+0

@Andrie. Burada bile çalışmıyor. 7 eleman listesinden ziyade 3 sütun veri çerçevesi sağlar. –

cevap

8

Burada bir çözüme benim atış yapmak olacaktır. Hem test durumlarınızda hem de test ettiğim birkaç konuda iyi çalışır.

## Because deprint() interprets numbers without a decimal part as integers, 
## I've modified L slightly, changing "list(w=2,4)" to "list(w=2L,4L)" 
## to allow a meaningful test using identical(). 
L <- 
structure(list(a = structure(list(d = 1:2, j = 5:6, o = structure(list(
    w = 2L, 4L), .Names = c("w", ""))), .Names = c("d", "j", "o" 
)), b = "c", c = 3:4), .Names = c("a", "b", "c")) 

## Capture the print representation of L, and then feed it to deprint() 
test2 <- capture.output(L) 
LL <- deprint(test2) 
identical(L, LL) 
## [1] TRUE 
LL 
## $a 
## $a$d 
## [1] 1 2 
## 
## $a$j 
## [1] 5 6 
## 
## $a$o 
## $a$o$w 
## [1] 2 
## 
## $a$o[[2]] 
## [1] 4 
## 
## $b 
## [1] "c" 
## 
## $c 
## [1] 3 4 

Ve işte, senin daha düzenli liste test baskı temsilini nasıl işleyeceğini var:

deprint(test) 
## [[1]] 
## [1] 1.0000 1.9643 4.5957 
## 
## [[2]] 
## [1] 1.0000 2.2753 3.8589 
## 
## [[3]] 
## [1] 1.0000 2.9781 4.5651 
## 
## [[4]] 
## [1] 1.0000 2.9320 3.5519 
## 
## [[5]] 
## [1] 1.0000 3.5772 2.8560 
## 
## [[6]] 
## [1] 1.0000 4.0150 3.1937 
## 
## [[7]] 
## [1] 1.0000 3.3814 3.4291 
L ile

deprint <- function(ll) { 
    ## Pattern to match strings beginning with _at least_ one $x or [[x]] 
    branchPat <- "^(\\$[^$[]*|\\[\\[[[:digit:]]*\\]\\])" 
    ## Pattern to match strings with _just_ one $x or one [[x]] 
    trunkPat <- "^(\\$[^$[]*|\\[\\[[[:digit:]]*\\]\\])\\s*$" 
    ## 
    isBranch <- function(X) { 
     grepl(branchPat, X[1]) 
    } 
    ## Parse character vectors of lines like "[1] 1 3 4" or 
    ## "[1] TRUE FALSE" or c("[1] a b c d", "[5] e f") 
    readTip <- function(X) { 
     X <- paste(sub("^\\s*\\[.*\\]", "", X), collapse=" ") 
     tokens <- scan(textConnection(X), what=character(), quiet=TRUE) 
     read.table(text = tokens, stringsAsFactors=FALSE)[[1]] 
    } 

    ## (0) Split into vector of lines (if needed) and 
    ##  strip out empty lines 
    ll <- readLines(textConnection(ll)) 
    ll <- ll[ll!=""] 

    ## (1) Split into branches ... 
    trunks <- grep(trunkPat, ll) 
    grp <- cumsum(seq_along(ll) %in% trunks) 
    XX <- split(ll, grp) 
    ## ... preserving element names, where present 
    nms <- sapply(XX, function(X) gsub("\\[.*|\\$", "", X[[1]])) 
    XX <- lapply(XX, function(X) X[-1]) 
    names(XX) <- nms 

    ## (2) Strip away top-level list identifiers. 
    ## pat2 <- "^\\$[^$\\[]*" 
    XX <- lapply(XX, function(X) sub(branchPat, "", X)) 

    ## (3) Step through list elements: 
    ## - Branches will need further recursive processing. 
    ## - Tips are ready to parse into base type vectors. 
    lapply(XX, function(X) { 
     if(isBranch(X)) deprint(X) else readTip(X) 
    }) 
} 

, sizin daha karmaşık bir örnek listesi burada ne verir

Bir örnek daha:

head(as.data.frame(deprint(capture.output(as.list(mtcars))))) 
# mpg cyl disp hp drat wt qsec vs am gear carb 
# 1 21.0 6 160 110 3.90 2.620 16.46 0 1 4 4 
# 2 21.0 6 160 110 3.90 2.875 17.02 0 1 4 4 
# 3 22.8 4 108 93 3.85 2.320 18.61 1 1 4 1 
# 4 21.4 6 258 110 3.08 3.215 19.44 1 0 3 1 
# 5 18.7 8 360 175 3.15 3.440 17.02 0 0 3 2 
# 6 18.1 6 225 105 2.76 3.460 20.22 1 0 3 1 
+0

Benim için de çalışıyor. Teşekkürler. –

+0

Dünkü ödülünü vermeyi planlamıştım. cevap, ama bir mesaj var bugün beni uyarmak için geri geldi ve geri geldi ve geri geldi mavi +500 simgesi –

+0

@BondedDust - Teşekkürler. Bu oldukça cömert bir ödül oldu. Başkalarını dağıtmak ve soracak olursak diğer soruları da ekleyelim: –

4
ben demezdim

"zarif", ama isimsiz listeler için, bu satırlar boyunca bir şey için bazı kontrol/değişiklikler yapabileceği "[[].]".

elbette
s <- strsplit(gsub("\\[+\\d+\\]+", "", test), "\n+")[[1]][-1] 
lapply(s, function(x) scan(text = x, what = double(), quiet = TRUE)) 

[[1]] 
[1] 1.0000 1.9643 4.5957 

[[2]] 
[1] 1.0000 2.2753 3.8589 

[[3]] 
[1] 1.0000 2.9781 4.5651 

[[4]] 
[1] 1.0000 2.9320 3.5519 

[[5]] 
[1] 1.0000 3.5772 2.8560 

[[6]] 
[1] 1.0000 4.0150 3.1937 

[[7]] 
[1] 1.0000 3.3814 3.4291 

, bu sadece listelerde özeldir ve bu özel örnekte özellikle what = double(), bu nedenle ek checki gerektirecektir ng. Listedeki karakter elemanlarını tespit etmek için benim aklına bir fikir what argüman

what = if(length(grep("\"", x))) character() else double() 
+0

Vektör satırlarını test etmek için hangi tür taramanın çalıştığını belirlemek için "" ile test edebilirsiniz. –

İlgili konular