我有一系列看起来像这样的文本文件:
USABILITY DATA
Level Name: LVL_Introduction
Time Spent: 323.233307
Times Teleported: 6
NumDeaths: 0
Level Name: LVL_1-1
Time Spent: 36.760727
Times Teleported: 1
NumDeaths: 0
Level Name: LVL_1-2
Time Spent: 45.953598
Times Teleported: 1
NumDeaths: 0
Level Name: LVL_1-3
Time Spent: 176.440704
Times Teleported: 0
NumDeaths: 0
Level Name: LVL_1-4
Time Spent: 281.797485
Times Teleported: 0
NumDeaths: 0
每个文本文件代表一个玩家来自益智游戏中从一个级别到另一个级别的游戏会话的数据。有些玩家达到的程度与其他玩家不同。
我想把这种文本文件刮到一个数据框中,这个数据框会给我一个带有Level Name的表(例如:“LVL_1-3”)作为列标题和“Time Spent”,“Times Teleported” “和”NumDeaths“作为行标题。
LVL_Introduction Lvl_1-1 etc...
Time Spent: 323.233307 36.760727
Times Teleported: 6 1
NumDeath: 0 0
理想情况下,无论涉及哪个用户(或级别名称),脚本都足够强大。我已经看到了几个相关问题的不同解决方案,一些使用正则表达式,一些只是拆分字符串。我不确定在一个跨多个文件的脚本中使用单行来生成标题和数据值的最佳过程。
谢谢, 米切尔
答案 0 :(得分:0)
这是我的建议,虽然它与您要求的不完全相符,但我认为您会发现它以非常整洁(阅读:有用)的方式为您提供数据:
library( readr )
library( plyr )
import <- function( datafile.name ) {
new <- read_delim( datafile.name,
col_names = c( "category", "data" ),
delim = ":",
trim_ws = TRUE )
new <- new[ !is.na( new$data ), ]
output <- data.frame(
new[ new$category == "Level Name", "data" ],
new[ new$category == "Time Spent", "data" ],
new[ new$category == "Times Teleported", "data" ],
new[ new$category == "NumDeaths", "data" ],
stringsAsFactors = FALSE
)
names( output ) <- c( "level.name", "time.spent", "times.teleported", "num.deaths" )
# get the username from the file name
output$user <- datafile.name
return( output )
}
# get a list of files
setwd( [where your files are located] )
filelist <- list.files()
# and apply the function above to all those files to create one big dataframe
df <- ldply( .data = filelist,
.fun = import )
注意,我假设您的文件名不直接代表用户名,因此您需要进行转换。像gsub(".txt","",datafile.name)
这样简单的东西就足够了。
如果要导入大量文件,您可能还希望多线程处理该进程。这里有4个核心:
library( doMC )
registerDoMC( cores = 4 )
df <- ldply( .data = filelist,
.fun = import,
.parallel = TRUE )
答案 1 :(得分:0)
readr
有一个很好的分块读取功能,如果你有分块的格式化数据,它可能会有所帮助。
在这里,我创建了一个处理块的函数 - 它使用read.delim
来读取variable: value
数据,然后使用tidyr::spread
转换它
library(tidyr)
library(readr)
f <- function(x, pos) {
dat <- read.delim(text = x, sep = ":", header = FALSE, stringsAsFactors = FALSE)
return(spread(dat, V1, V2))
}
使用DataFrameCallback
阅读包含data.frame
rbind
个结果
rawData <- read_lines_chunked(file = "gamedata.txt",
skip = 1,
chunk_size = 5,
callback = DataFrameCallback$new(f))
然后,只需将此格式重新格式化为您要求的内容(使用4
列ID不健全,但这是一个干净的示例)
gameData <- setNames(data.frame(t(rawData[, -4])), rawData[, 4])[c(2,3,1), ]
gameData
#> LVL_Introduction LVL_1-1 LVL_1-2 LVL_1-3
#> Time Spent 323.233307 36.760727 45.953598 176.440704
#> Times Teleported 6 1 1 0
#> NumDeaths 0 0 0 0
#> LVL_1-4
#> Time Spent 281.797485
#> Times Teleported 0
#> NumDeaths 0