2017-12-21 12 views
0

Ich versuche, eine 2-Spalten-Liste zu analysieren, die durch mehrere Leerzeichen für Spalten und einzelne Leerzeichen für Wörter innerhalb einer Spalte getrennt ist. Nichts, was ich versucht habe, hat die Daten erfolgreich in zwei Spalten aufgeteilt. Wie mache ich das?Fread Angabe Trennzeichen in der Spalte

library(data.table) 
item.ids<-fread("http://eve-files.com/chribba/typeid.txt",sep2=" ") 

Beispiel des Datensatzes:

typeID  typeName 
----------- ---------------------------------------- 
0   #System 
2   Corporation 
3   Region 
4   Constellation 
5   Solar System 
+1

, dass mehr sieht aus wie es eher feste Breite ist als delimted. Schau dir "iotools" oder die "readr" -Pakete an. Außerdem wäre dieses '#' ein Problem, wenn Sie es nicht berücksichtigen. – A5C1D2H2I1M1N2O1R2T1

+1

Oder einfach 'read.fwf' in der Basis. – Gregor

Antwort

1

Dies scheint zu funktionieren:

library(readr) 
url = "http://eve-files.com/chribba/typeid.txt" 
df = read_fwf(url, fwf_empty(url), skip = 2) 
colnames = read_table(url, n_max = 1) 
names(df) = names(colnames) 
df = na.omit(df) 

dim(df) 
# [1] 22382  2 
summary(df) 
# typeID   typeName   
# Min. :  0 Length:22382  
# 1st Qu.: 13986 Class :character 
# Median : 22938 Mode :character 
# Mean : 53827      
# 3rd Qu.: 30209      
# Max. :368620  
+0

Das war, was ich mit meinem ursprünglichen Kommentar im Sinn hatte, aber nicht weiter erforschte. +1 – A5C1D2H2I1M1N2O1R2T1

+0

Ja, ich war wirklich überrascht, dass du diese Route in deiner Antwort nicht gegangen bist. Ich habe ein wenig mit 'read.fwf' versucht, aber es gab meine Probleme mit Zeilennamen und es schien nervig zu beheben. Die 'readr'-Version ist viel freundlicher. – Gregor

+0

Die Basis 'read.fwf' ist sehr langsam, also ist' read_fwf' eigentlich eine sehr willkommene Ergänzung zu Dateieingabemöglichkeiten .... – A5C1D2H2I1M1N2O1R2T1

1

Hier ist ein Ansatz, der extract von „tidyr“ verwendet, die ziemlich einfach sein sollte zu folgen.

Zuerst lesen wir die Daten ein und inspizieren die ersten Zeilen und letzten Zeilen. Nach der Inspektion finden wir, dass die Datenwerte aus Linien 3 bis 22384.

x <- readLines("http://eve-files.com/chribba/typeid.txt") 
# Check out the data 
head(x) # Let's get rid of the first two lines... 
tail(x) # ... and the last 3 

In der Extraktionsstufe, sind wir im Grunde suchen:

  • Eine Reihe von Zahlen - kann sein unterschiedliche Längen (([0-9]+)). Es ist in (), also erfassen Sie es und extrahieren Sie es in eine neue Spalte.
  • Den Nummern sollten 2 oder mehr Leerzeichen folgen ([ ]{2,}). Das ist nicht in (), also müssen wir das nicht in eine neue Spalte extrahieren.
  • Die Menge der Leerzeichen kann von allem anderen gefolgt werden ((.*)). Das ist in (), also erfassen Sie das und extrahieren Sie es in eine neue Spalte.

Ich habe auch den ersten Wert von "x" verwendet, um die ursprünglichen Spaltennamen zu extrahieren.

Hier ist, wie es aussieht:

library(tidyverse) 
data_frame(V1 = x[3:(length(x)-3)]) %>% 
    extract(V1, into = scan(text = x[1], what = ""), regex = "([0-9]+)[ ]{2,}(.*)") 
# # A tibble: 22,382 x 2 
# typeID   typeName 
# * <chr>    <chr> 
# 1  0   #System 
# 2  2  Corporation 
# 3  3    Region 
# 4  4  Constellation 
# 5  5  Solar System 
# 6  6 Sun G5 (Yellow) 
# 7  7 Sun K7 (Orange) 
# 8  8 Sun K5 (Red Giant) 
# 9  9  Sun B0 (Blue) 
# 10  10  Sun F0 (White) 
# # ... with 22,372 more rows 

Oder

data_frame(V1 = x[3:(length(x)-3)]) %>% 
    separate(V1, into = scan(text = x[1], what = ""), sep = "[ ]{2,}", 
      extra = "merge", convert = TRUE) 

Ein anderer Ansatz strsplit mit [ ]{2, } als Split-Wert zu verwenden sein könnte. do.call(rbind, ...) wäre das Idiom danach zu folgen, aber Sie möchten vielleicht nur für Fälle filtern, in denen der Split zu zwei Werten führte.

do.call(rbind, Filter(function(z) length(z) == 2, strsplit(x, "[ ]{2, }"))) 
0

lesen in Ihrer Textdatei line-by-line:

l <- list() 
fileName <- "http://eve-files.com/chribba/typeid.txt" 
conn <- file(fileName,open="r") 
linn <-readLines(conn) 
for (i in 1:length(linn)){ 
    l[i] <- list(linn[i]) 
} 
close(conn) 

Erstellen Sie eine Liste aller Einträge:

l_new <- list() 
for(p in 1:length(l)) { 

    new_vec <- unlist(strsplit(gsub("(?<=[\\s])\\s*|^\\s+|\\s+$", "", l[[p]], perl=TRUE), " ")) 

    if(!is.na(new_vec[4])) { 
     new_vec_t <- paste(new_vec[2], new_vec[3], new_vec[4]) 
    } 
    else if (!is.na(new_vec[3])) { 
     new_vec_t <- paste(new_vec[2], new_vec[3]) 
    } 
    else { 
     new_vec_t <- paste(new_vec[2]) 
    } 

    l_new[p] <- list(c(new_vec[1], new_vec_t)) 

} 

Konvertieren Sie Ihre Liste in einen Datenrahmen:

l_new_frame <- data.frame(do.call('rbind', l_new)) 

l_new_frame <- l_new_frame[-c(1,2),] 
names(l_new_frame) <- c('typeID', 'typeName') 

prüfen Ergebnisse:

print(l_new_frame[1:100,], row.names = FALSE) 

enter image description here

Verwandte Themen