fread指定列内的分隔符

问题描述 投票:0回答:3

我试图解析一个2列列表,使用多个空格分隔列,单个空格用于列中的单词。我没有尝试过将数据成功分成两列。我该怎么做呢?

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
r dataset
3个回答
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    

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)

另一种方法可能是使用strsplit[ ]{2, }作为分裂值。在此之后,do.call(rbind, ...)将成为惯用语,但您可能只想过滤分裂导致两个值的情况。

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

© www.soinside.com 2019 - 2024. All rights reserved.