如何混合型矩阵转换为数据帧中的朱莉娅承认列类型
DataFrames的一个很好的特性是,它可以存储不同类型的列,它可以“自动识别”出来的,例如:如何混合型矩阵转换为数据帧中的朱莉娅承认列类型
using DataFrames, DataStructures
df1 = wsv"""
parName region forType value
vol AL broadL_highF 3.3055628012
vol AL con_highF 2.1360975151
vol AQ broadL_highF 5.81984502
vol AQ con_highF 8.1462998309
"""
typeof(df1[:parName])
DataArrays.DataArray{String,1}
typeof(df1[:value])
DataArrays.DataArray{Float64,1}
当我尝试做不过来达到相同的结果从一开始矩阵(从电子表格导入)I“松”即自动转换:
dataMatrix = [
"parName" "region" "forType" "value";
"vol" "AL" "broadL_highF" 3.3055628012;
"vol" "AL" "con_highF" 2.1360975151;
"vol" "AQ" "broadL_highF" 5.81984502;
"vol" "AQ" "con_highF" 8.1462998309;
]
h = [Symbol(c) for c in dataMatrix[1,:]]
vals = dataMatrix[2:end, :]
df2 = convert(DataFrame,OrderedDict(zip(h,[vals[:,i] for i in 1:size(vals,2)])))
typeof(df2[:parName])
DataArrays.DataArray{Any,1}
typeof(df2[:value])
DataArrays.DataArray{Any,1}
上有SO几个问题关于如何将矩阵转换为数据框(例如DataFrame from Array with Header,Convert Julia array to dataframe),但没有任何答案处理混合类型矩阵的转换。
如何从矩阵自动识别列的类型创建一个数据框? (1)转换df(使用字典或矩阵构造函数..第一个更快)然后应用try-catch进行类型转换(我的原始答案); (2)转换为字符串,然后使用df.inlinetable(丹Getz答案); (3)检查每个元素的类型和列的一致性(Alexander Morley答案)。
这些结果如下:
# second time for compilation.. further times ~ results
@time toDf1(m) # 0.000946 seconds (336 allocations: 19.811 KiB)
@time toDf2(m) # 0.000194 seconds (306 allocations: 17.406 KiB)
@time toDf3(m) # 0.001820 seconds (445 allocations: 35.297 KiB)
那么,疯狂的是,最有效的解决方案似乎是“倒出来的水”问题缩小到一个已经解决了一个;-)
谢谢你所有的答案。
另一种方法是重用工作解决方案,即将矩阵转换为适合DataFrames使用的字符串。在代码中,这是:
using DataFrames
dataMatrix = [
"parName" "region" "forType" "value";
"vol" "AL" "broadL_highF" 3.3055628012;
"vol" "AL" "con_highF" 2.1360975151;
"vol" "AQ" "broadL_highF" 5.81984502;
"vol" "AQ" "con_highF" 8.1462998309;
]
s = join(
[join([dataMatrix[i,j] for j in indices(dataMatrix, 2)]
, '\t') for i in indices(dataMatrix, 1)], '\n')
df = DataFrames.inlinetable(s; separator='\t', header=true)
所得df
具有由数据帧猜到其列类型。
无关,但这个答案让我想起how a mathematician boils water joke。
我正在使用'writecsv '写一个'IOBuffer',然后''readtable',让它不停地取笑我。这让人想起这一点,但我认为更清洁。 –
@ MichaelK.Borregaard写给IOBuffer也是这个解决方案的第一个版本(但是在摆脱尾随选项卡时,编辑到这个版本让我恼火)。 –
啊 - 无关 - 但你是如何获得'readtable'来接受'IOBuffer'输入的?我可以做'a = IOBuffer(); writecsv(a,dataMatrix); readcsv(take!(a),DataFrame))',但我无法使用'CSV.read'或'readtable'工作。 –
虽然我没有找到一个完整的解决方案,部分之一,是尝试将各列事后转换:
"""
convertDf!(df)
Try to convert each column of the converted df from Any to In64, Float64 or String (in that order).
"""
function convertDf!(df)
for c in names(df)
try
df[c] = convert(DataArrays.DataArray{Int64,1},df[c])
catch
try
df[c] = convert(DataArrays.DataArray{Float64,1},df[c])
catch
try
df[c] = convert(DataArrays.DataArray{String,1},df[c])
catch
end
end
end
end
end
尽管肯定不完整的,这是足以让我的需求。
虽然我认为可能有更好的方式去做所有事情,这应该做你想做的事情。
df = DataFrame()
for (ind,s) in enumerate(Symbol.(dataMatrix[1,:])) # convert first row to symbols and iterate through them.
# check all types the same else assign to Any
T = typeof(dataMatrix[2,ind])
T = all(typeof.(dataMatrix[2:end,ind]).==T) ? T : Any
# convert to type of second element then add to data frame
df[s] = T.(dataMatrix[2:end,ind])
end
mat2df(mat) =
DataFrame([[mat[2:end,i]...] for i in 1:size(mat,2)], Symbol.(mat[1,:]))
似乎工作,且比@丹 - 盖茨的答案(至少在这个数据矩阵):)
using DataFrames, BenchmarkTools
dataMatrix = [
"parName" "region" "forType" "value";
"vol" "AL" "broadL_highF" 3.3055628012;
"vol" "AL" "con_highF" 2.1360975151;
"vol" "AQ" "broadL_highF" 5.81984502;
"vol" "AQ" "con_highF" 8.1462998309;
]
mat2df(mat) =
DataFrame([[mat[2:end,i]...] for i in 1:size(mat,2)], Symbol.(mat[1,:]))
function mat2dfDan(mat)
s = join([join([dataMatrix[i,j] for j in indices(dataMatrix, 2)], '\t')
for i in indices(dataMatrix, 1)],'\n')
DataFrames.inlinetable(s; separator='\t', header=true)
end
更快 -
julia> @benchmark mat2df(dataMatrix)
BenchmarkTools.Trial:
memory estimate: 5.05 KiB
allocs estimate: 75
--------------
minimum time: 18.601 μs (0.00% GC)
median time: 21.318 μs (0.00% GC)
mean time: 31.773 μs (2.50% GC)
maximum time: 4.287 ms (95.32% GC)
--------------
samples: 10000
evals/sample: 1
julia> @benchmark mat2dfDan(dataMatrix)
BenchmarkTools.Trial:
memory estimate: 17.55 KiB
allocs estimate: 318
--------------
minimum time: 69.183 μs (0.00% GC)
median time: 81.326 μs (0.00% GC)
mean time: 90.284 μs (2.97% GC)
maximum time: 5.565 ms (93.72% GC)
--------------
samples: 10000
evals/sample: 1
你为什么不只是保存电子表格中的csv文件并使用CSV.read()加载它?这应该照顾它。 –
@ MichaelK.Borregaard,因为我有一个模型可以加载来自多张工作表的所有设置和数据,并且我希望在每次进行更改时都避免将它们全部导出到CVS。 – Antonello