2017-12-21 3 views
0

カラムの複数のスペースとカラムのワードのためのシングルスペースで区切られた2つのカラムリストを解析しようとしています。私が試みたことは、データを2つの列に分割することに成功したものではありません。これはどうすればいいですか?データセットのfreadはカラム内にセパレータを指定しています

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

例:

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

それは一定の幅ではなくdelimtedだよりのように見えます。 "iotools"または "readr"パッケージを見てください。また、あなたがそれを考慮しなければ、 '#'は問題になります。 – A5C1D2H2I1M1N2O1R2T1

+1

または単に 'read.fwf'をベースにします。 – Gregor

答えて

1

これは動作するようです:テキストファイルの行ごとで

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

これは私の元のコメントで念頭に置いていたものですが、それ以上は探っていませんでした。 +1 – A5C1D2H2I1M1N2O1R2T1

+0

ええ、私は本当にあなたの答えでそのルートを行っていない驚いた。私は 'read.fwf'でちょっと試しましたが、行の名前に問題があり、修正するのは面倒だったようです。 'readr'版ははるかに面白いです。 – Gregor

+0

ベース 'read.fwf'は非常に遅いので、' read_fwf'は実際にはファイル入力オプションに非常に歓迎されています.... – A5C1D2H2I1M1N2O1R2T1

1

ここで従うのはかなり簡単なはず「tidyr」からextractを使用する一つの方法です。

まず、データを読み込み、最初の数行と最後の数行を調べます。検査の後、我々はデータ値がラインから3抽出段階で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 

にあることがわかり、私たちは基本的に探している:

  • 数の集合 - 可能であること様々な長さ(([0-9]+))。それは()にあるので、それをキャプチャして新しい列に抽出します。
  • 数字の後に2つ以上のスペース([ ]{2,})を続けてください。それは()にはないので、新しい列にそれを抽出する必要はありません。
  • 空白のセットの後ろに他のもの((.*))を付けることができます。これは()にあるので、それをキャプチャして新しい列に抽出します。

"x"の最初の値を使用して元の列名を抽出しました。ここで

が、それは次のようになります。

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 

それとも

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

別のアプローチは、分割値として[ ]{2, }strsplitを使用するのが良いかもしれません。それに続くのは、do.call(rbind, ...)ですが、スプリットで2つの値が生じた場合にのみフィルタリングしたい場合があります。

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

読む:

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) 

は、すべてのエントリのリストを作成します:

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)) 

} 

リストをデータフレームに変換:

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') 

チェック結果:

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

enter image description here

関連する問題