如何将.js文件读入DataFrame

时间:2018-03-26 11:38:01

标签: dataframe file-io julia

我有以下非标准文件,并希望有效地将其读入Dataframe,但不知道如何有效地处理它。

m[mi++]="18.06.16 22:00:00|0;3;1;1667;49;49;12|0;17;3;2153;328;153;57|0;18;0;2165;284;156;53"
m[mi++]="18.06.16 21:55:00|0;24;7;1667;306;306;61|0;21;4;2153;384;166;62|0;19;1;2165;368;185;62"
m[mi++]="18.06.16 21:50:00|0;31;6;1667;394;349;62|0;32;6;2153;402;164;63|0;33;4;2165;380;171;63"
m[mi++]="18.06.16 21:45:00|11;50;19;1667;390;312;63|34;61;9;2153;410;166;63|19;60;8;2165;391;185;63"
m[mi++]="18.06.16 21:40:00|37;63;24;1666;387;313;63|55;80;12;2150;418;169;64|46;79;11;2163;398;186;63"

如果我已将此数据保存在文件a.js中,则以下代码有效:

b = readtable("a.js")
dat_5m = DataFrame(t=DateTime[], Pac_1=Float64[], Pdc_A1=Float64[], Pdc_B1=Float64[], Etot1=Float64[],
    U_A1=Float64[], U_B1=Float64[], T_1=Float64[], Pac_2=Float64[], Pdc_A2=Float64[], Pdc_B2=Float64[],
    Etot2=Float64[], U_A2=Float64[], U_B2=Float64[], T_2=Float64[], Pac_3=Float64[], Pdc_A3=Float64[],
    Pdc_B3=Float64[], Etot3=Float64[], U_A3=Float64[], U_B3=Float64[], T_3=Float64[])
for r in nrow(b):-1:1
   c = split(b[r,1], [';','|','=']);
   d = float(c[3:end])'
   t = DateTime(c[2], DateFormat("dd.mm.yy HH:MM:SS"))
   push!(dat_5m, [t d])
end

但我认为它非常不优雅。有没有更有效的方法?

1 个答案:

答案 0 :(得分:1)

如果可能(IO允许),我建议先清理文件,删除|以及任何时髦的"和前缀。然后,您可以使用CSV.jl让您的生活更轻松。

过程是:逐行阅读,清理每一行,然后使用CSV将其读回:

julia> using CSV

julia> open("b.js", "a") do new_file
           for line in readlines("a.js")
               line = replace(line, "m[mi++]=\"", "")
               # remove only trailing quote
               line = replace(line, r"\"$", "")
               line = replace(line, "|", ";")
               write(new_file, string(line, "\n"))
           end
       end


julia> b = CSV.read("b.js",
           delim = ";",
           header = false, # change this to a string vector to provide column names
           dateformat = "dd.mm.yy HH:MM:SS");

julia> # correct times to be in 2016
       b[:Column1] += Dates.Year(2000);

julia> head(b)
6×22 DataFrames.DataFrame. Omitted printing of 15 columns
│ Row │ Column1             │ Column2 │ Column3 │ Column4 │ Column5 │ Column6 │ Column7 │
├─────┼─────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤
│ 1   │ 2016-06-18T22:00:00 │ 0       │ 3       │ 1       │ 1667    │ 49      │ 49      │
│ 2   │ 2016-06-18T21:55:00 │ 0       │ 24      │ 7       │ 1667    │ 306     │ 306     │
│ 3   │ 2016-06-18T21:50:00 │ 0       │ 31      │ 6       │ 1667    │ 394     │ 349     │
│ 4   │ 2016-06-18T21:45:00 │ 11      │ 50      │ 19      │ 1667    │ 390     │ 312     │
│ 5   │ 2016-06-18T21:40:00 │ 37      │ 63      │ 24      │ 1666    │ 387     │ 313     │
│ 6   │ 2016-06-18T22:00:00 │ 0       │ 3       │ 1       │ 1667    │ 49      │ 49      │

我一步一步地清理这些线条,使这个过程更容易理解。如果你是一名正则表达式大师,你可能想要在一行中做到这一点。

可能有更好的方法来处理2位数年份,所以如果有人知道如何解决这个问题,请编辑此答案或将其添加为评论。谢谢!

编辑: 如果您想在不写入其他文件的情况下执行相同的操作,则可以通过将CSV.read()数组再次转换为readlines来重新应用清除功能,并重新使用IOBuffer

function cleaner(line)
    line = replace(line, "m[mi++]=\"", "")
    line = replace(line, r"\"$", "")
    line = replace(line, "|", ";")
    println(line)
    string(line, "\n")
end

c = CSV.read(
    Base.IOBuffer(
        string(cleaner.(readlines("a.js"))...)),
        delim = ";",
        header = false,
        dateformat = "dd.mm.yy HH:MM:SS");

c[:Column1] += Dates.Year(2000);

这给出了与其他解决方案相同的结果。