首页 > 解决方案 > 如何从带有标头的 XLSX.readdata() 对象创建 DataFrame?

问题描述

我正在尝试按如下方式创建 DataFrame 对象:

julia> using DataFrames

julia> using XLSX

julia> T = XLSX.readdata("zillow_data_download_april2020.xlsx", #filename,
           "Sale_counts_city", #sheet name,
           "A1:F9" #cell range,
           )
9×6 Array{Any,2}:
      "RegionID"  "RegionName"    "StateName"      "SizeRank"      "2008-03"      "2008-04"
  6181            "New York"      "New York"      1                missing        missing
 12447            "Los Angeles"   "California"    2            1446           1705
 39051            "Houston"       "Texas"         3            2926           3121
 17426            "Chicago"       "Illinois"      4            2910           3022
  6915            "San Antonio"   "Texas"         5            1479           1529
 13271            "Philadelphia"  "Pennsylvania"  6            1609           1795
 40326            "Phoenix"       "Arizona"       7            1310           1519
 18959            "Las Vegas"     "Nevada"        8            1618           1856
    
julia> typeof(T)
Array{Any,2}

标头成为数据的一部分:

julia> DataFrame(T)
9×6 DataFrame
│ Row │ x1       │ x2           │ x3           │ x4       │ x5      │ x6      │
│     │ Any      │ Any          │ Any          │ Any      │ Any     │ Any     │
├─────┼──────────┼──────────────┼──────────────┼──────────┼─────────┼─────────┤
│ 1   │ RegionID │ RegionName   │ StateName    │ SizeRank │ 2008-03 │ 2008-04 │
│ 2   │ 6181     │ New York     │ New York     │ 1        │ missing │ missing │
│ 3   │ 12447    │ Los Angeles  │ California   │ 2        │ 1446    │ 1705    │
│ 4   │ 39051    │ Houston      │ Texas        │ 3        │ 2926    │ 3121    │
│ 5   │ 17426    │ Chicago      │ Illinois     │ 4        │ 2910    │ 3022    │
│ 6   │ 6915     │ San Antonio  │ Texas        │ 5        │ 1479    │ 1529    │
│ 7   │ 13271    │ Philadelphia │ Pennsylvania │ 6        │ 1609    │ 1795    │
│ 8   │ 40326    │ Phoenix      │ Arizona      │ 7        │ 1310    │ 1519    │
│ 9   │ 18959    │ Las Vegas    │ Nevada       │ 8        │ 1618    │ 1856    │

没有标题的数据框:

julia> DataFrame(T[2:9,:])
8×6 DataFrame
│ Row │ x1    │ x2           │ x3           │ x4  │ x5      │ x6      │
│     │ Any   │ Any          │ Any          │ Any │ Any     │ Any     │
├─────┼───────┼──────────────┼──────────────┼─────┼─────────┼─────────┤
│ 1   │ 6181  │ New York     │ New York     │ 1   │ missing │ missing │
│ 2   │ 12447 │ Los Angeles  │ California   │ 2   │ 1446    │ 1705    │
│ 3   │ 39051 │ Houston      │ Texas        │ 3   │ 2926    │ 3121    │
│ 4   │ 17426 │ Chicago      │ Illinois     │ 4   │ 2910    │ 3022    │
│ 5   │ 6915  │ San Antonio  │ Texas        │ 5   │ 1479    │ 1529    │
│ 6   │ 13271 │ Philadelphia │ Pennsylvania │ 6   │ 1609    │ 1795    │
│ 7   │ 40326 │ Phoenix      │ Arizona      │ 7   │ 1310    │ 1519    │
│ 8   │ 18959 │ Las Vegas    │ Nevada       │ 8   │ 1618    │ 1856    │

使用标题创建时引发错误:

julia> DataFrame(T[2:9,:],T[1,:])
ERROR: MethodError: no method matching DataFrame(::Array{Any,2}, ::Array{Any,1})
Closest candidates are:
  DataFrame(::AbstractArray{T,2} where T) at /opt/julia/julia-1.4.1/share/julia/stdlib/v1.4/packages/DataFrames/yH0f6/src/dataframe/dataframe.jl:209
  DataFrame(::AbstractArray{T,2} where T, ::AbstractArray{Symbol,1}; makeunique) at /opt/julia/julia-1.4.1/share/julia/stdlib/v1.4/packages/DataFrames/yH0f6/src/dataframe/dataframe.jl:209
  DataFrame(::T; copycols) where T at /opt/julia/julia-1.4.1/share/julia/stdlib/v1.4/packages/DataFrames/yH0f6/src/other/tables.jl:23
Stacktrace:
 [1] top-level scope at REPL[19]:1

更新1

参考PaSTE的解决方案:

julia> DataFrame(T[2:end,:], convert(Vector{String},T[1,:]))
ERROR: MethodError: no method matching DataFrame(::Array{Any,2}, ::Array{String,1})
Closest candidates are:
  DataFrame(::AbstractArray{T,2} where T) at /opt/julia/julia-1.4.1/share/julia/stdlib/v1.4/packages/DataFrames/yH0f6/src/dataframe/dataframe.jl:209
  DataFrame(::AbstractArray{T,2} where T, ::AbstractArray{Symbol,1}; makeunique) at /opt/julia/julia-1.4.1/share/julia/stdlib/v1.4/packages/DataFrames/yH0f6/src/dataframe/dataframe.jl:209
  DataFrame(::T; copycols) where T at /opt/julia/julia-1.4.1/share/julia/stdlib/v1.4/packages/DataFrames/yH0f6/src/other/tables.jl:23
Stacktrace:
 [1] top-level scope at REPL[19]:1

请指导我从带有标头的 XLSX.readdata() 对象创建 DataFrame。

更新2:

我在试错法中得到了它:

julia> df2=DataFrame(T[2:end,:], Symbol.(vec(T[1,:])))
8×6 DataFrame
│ Row │ RegionID │ RegionName   │ StateName    │ SizeRank │ 2008-03 │ 2008-04 │
│     │ Any      │ Any          │ Any          │ Any      │ Any     │ Any     │
├─────┼──────────┼──────────────┼──────────────┼──────────┼─────────┼─────────┤
│ 1   │ 6181     │ New York     │ New York     │ 1        │ missing │ missing │
│ 2   │ 12447    │ Los Angeles  │ California   │ 2        │ 1446    │ 1705    │
│ 3   │ 39051    │ Houston      │ Texas        │ 3        │ 2926    │ 3121    │
│ 4   │ 17426    │ Chicago      │ Illinois     │ 4        │ 2910    │ 3022    │
│ 5   │ 6915     │ San Antonio  │ Texas        │ 5        │ 1479    │ 1529    │
│ 6   │ 13271    │ Philadelphia │ Pennsylvania │ 6        │ 1609    │ 1795    │
│ 7   │ 40326    │ Phoenix      │ Arizona      │ 7        │ 1310    │ 1519    │
│ 8   │ 18959    │ Las Vegas    │ Nevada       │ 8        │ 1618    │ 1856    │

标签: dataframejuliaxlsx

解决方案


考虑使用XLSX.readtable

让 XLSX.jl 以表格形式读取数据以供 DataFrame 解析的最简单方法是使用该XLSX.readtable方法而不是XLSX.readdata. 使用包用于测试的示例.xlsx文件:

XLSX.readtable("Book1.xlsx", # file name
               1,  # first sheet
)

结果:

(Any[Any[10.5, Dates.Date("2018-03-21"), Dates.Date("2018-03-21"), true, 1, "palavra1"], Any[21.2, Dates.Date("2018-03-22"), Dates.Date("2018-03-22"), false, 2, "palavra2"]], [:B2, :C2])

XLSX.readtable自动读取文件中的第一个非空行作为列标签。它还会自动跳过工作表左侧的空列。该文档建议如何将其读入DataFrame

运算符...会将元组 (data, column_labels) 放入 DataFrame 的构造函数中。

这意味着我们可以这样做:

df1 = DataFrame(XLSX.readtable("Book1.xlsx", 1)...)

结果:

6×2 DataFrame
 Row │ B2          C2
     │ Any         Any
─────┼────────────────────────
   1 │ 10.5        21.2
   2 │ 2018-03-21  2018-03-22
   3 │ 2018-03-21  2018-03-22
   4 │ true        false
   5 │ 1           2
   6 │ palavra1    palavra2

XLSX.readdata改为使用

如果您坚持使用XLSX.readdata,则必须手动将第一行转换为字符串向量:

data = XLSX.readdata("Book1.xlsx", 1, "B2:C8")
df2 = DataFrame(data[2:end,:], convert(Vector{String}, data[1,:]))

df1 == df2  # true

推荐阅读