Julia 如何将字典列表转换为数据帧?

Julia 如何将字典列表转换为数据帧?,julia,Julia,我有一个字典列表,其格式与下面类似。名单 是由我不想更改的其他函数生成的。因此, 列表及其目录的存在可以被视为一个给定值 dictlist=[] for i in 1:20 push!(dictlist, Dict(:a=>i, :b=>2*i)) end 是否有一种语法清晰的方法将此列表转换为数据帧?此函数提供了一种可能的解决方案: using DataFrames function DictionariesToDataFrame(dictlist) ret = Dic

我有一个字典列表,其格式与下面类似。名单 是由我不想更改的其他函数生成的。因此, 列表及其目录的存在可以被视为一个给定值

dictlist=[]
for i in 1:20
  push!(dictlist, Dict(:a=>i, :b=>2*i))
end

是否有一种语法清晰的方法将此列表转换为数据帧?

此函数提供了一种可能的解决方案:

using DataFrames

function DictionariesToDataFrame(dictlist)
  ret = Dict()                 #Holds dataframe's columns while we build it
  #Get all unique keys from dictlist and make them entries in ret
  for x in unique([y for x in [collect(keys(x)) for x in dictlist] for y in x])
    ret[x] = []
  end
  for row in dictlist          #Loop through each row
    for (key,value) in ret     #Use ret to check all possible keys in row
      if haskey(row,key)       #Is key present in row?
        push!(value, row[key]) #Yes
      else                     #Nope
        push!(value, nothing)  #So add nothing. Keeps columns same length.
      end
    end
  end
  #Fix the data types of the columns
  for (k,v) in ret                             #Consider each column
    row_type = unique([typeof(x) for x in v])  #Get datatypes of each row
    if length(row_type)==1                     #All rows had same datatype
      row_type = row_type[1]                   #Fetch datatype
      ret[k]   = convert(Array{row_type,1}, v) #Convert column to that type
    end
  end
  #DataFrame is ready to go!
  return DataFrames.DataFrame(ret)
end

#Generate some data
dictlist=[]
for i in 1:20
  push!(dictlist, Dict("a"=>i, "b"=>2*i))
  if i>10
    dictlist[end-1]["c"]=3*i
  end
end

DictionariesToDataFrame(dictlist)

没有好的直接方法(我知道),但是使用像这样的
数据帧
,您可以首先将其转换为
命名偶的列表

julia> using DataFrames

julia> dictlist=[]
0-element Array{Any,1}

julia> for i in 1:20
         push!(dictlist, Dict(:a=>i, :b=>2*i))
       end

julia> DataFrame([NamedTuple{Tuple(keys(d))}(values(d)) for d in dictlist])
20×2 DataFrame
│ Row │ a     │ b     │
│     │ Int64 │ Int64 │
├─────┼───────┼───────┤
│ 1   │ 1     │ 2     │
│ 2   │ 2     │ 4     │
│ 3   │ 3     │ 6     │
│ 4   │ 4     │ 8     │
│ 5   │ 5     │ 10    │
│ 6   │ 6     │ 12    │
│ 7   │ 7     │ 14    │
│ 8   │ 8     │ 16    │
│ 9   │ 9     │ 18    │
│ 10  │ 10    │ 20    │
│ 11  │ 11    │ 22    │
│ 12  │ 12    │ 24    │
│ 13  │ 13    │ 26    │
│ 14  │ 14    │ 28    │
│ 15  │ 15    │ 30    │
│ 16  │ 16    │ 32    │
│ 17  │ 17    │ 34    │
│ 18  │ 18    │ 36    │
│ 19  │ 19    │ 38    │
│ 20  │ 20    │ 40    │

请注意,就在今天,我将此作为一个应用程序打开,因此可能很快就会有更好的支持。

您可以
推送中的行(由字典表示)

根据

正如文档所说,这比逐列构造要慢得多,但并不比自己从dicts构造列慢

df = DataFrame()
for row in dictlist
    push!(df, row)
end

有一个 使
Vector{Dict}
a Tables.jl行表格类型。 如果这样做了(这似乎可能在一个月左右的时间内发生) 那你就可以这么做了

df = DataFrame(dictlist)

对于可能稀疏的帧,这里有一个不会丢失数据,但会添加丢失的数据:

using DataFrames

dictlist = [Dict("a" => 2), Dict("a" => 5, "b" => 8)]

keycol = unique(mapreduce(x -> collect(keys(x)), vcat, dictlist))

df = DataFrame()

df[!, Symbol("Keys")] = keycol

for (i, d) in enumerate(dictlist)
    df[!, Symbol(string(i))] = [get(d, k, missing) for k in keycol]
end

println(df)

仅作为参考,它的外观没有任何方法可用于将dict列表转换为数据帧。相反,我们将dict列表转换为dict of list。我的意思是从
[(:a=>1,:b=>2),(:a=>3,:b=>4)]
(:a=>[1,3],:b=>[2,4])
,所以我们需要创建这样的函数:

function to_dict_of_array(data::Array, fields::Array)
    # Pre allocate the array needed for speed up in case of large dataset
    doa = Dict(Symbol(field) => Array{Any}(undef, length(data)) for field in fields)
    for (i, datum) in enumerate(data)
        for fn in fields
            sym_fn = Symbol(fn)
            doa[sym_fn][i]  = datum[fn]
        end
    end
    return doa
end
然后我们可以使用该方法创建数据帧

array_of_dict = [Dict("a" => 1, "b" =>2), Dict("a" => 3, "b" =>4)]
required_field = ["a", "b"]
df = DataFrame(to_dict_of_array(array_of_dict, required_field));

这只是一个概念性的例子。应根据用例进行修改。

键是否始终相同?如果是这样的话,请澄清问题,以便正确开始。如果不是的话,可能会让你的考试更复杂一些,这样就表明他们可以有一些选择