Matrix 如何在列类型识别中将混合类型矩阵转换为数据帧
DataFrames的一个很好的特性是,它可以存储不同类型的列,并且可以“自动识别”它们,例如:Matrix 如何在列类型识别中将混合类型矩阵转换为数据帧,matrix,dataframe,type-conversion,julia,Matrix,Dataframe,Type Conversion,Julia,DataFrames的一个很好的特性是,它可以存储不同类型的列,并且可以“自动识别”它们,例如: using DataFrames, DataStructures df1 = wsv""" parName region forType value vol AL broadL_highF 3.3055628012 vol AL con_highF 2.1360975151 vol AQ
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}
然而,当我尝试从矩阵(从电子表格导入)开始获得相同的结果时,我“松开”了自动转换:
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}
关于S.O.如何将矩阵转换为数据帧(例如),有几个问题,但没有一个答案涉及混合类型矩阵的转换
如何从自动识别列类型的矩阵创建数据帧
编辑:I:(1)转换df(使用字典或矩阵构造函数..第一个更快),然后应用try-catch进行类型转换(我的原始答案);(2) 转换为字符串,然后使用df.inlinetable(Dan Getz answer);(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)
因此,疯狂的是,最有效的解决方案似乎是“倒水”,并将问题简化为已经解决的问题;-)
感谢您提供的所有答案。虽然我没有找到完整的解决方案,但部分解决方案是尝试事后转换各个列:
"""
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
虽然肯定不完整,但足以满足我的需要。虽然我没有找到完整的解决方案,但部分解决方案是尝试事后转换各个列:
"""
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
虽然我认为可能有更好的方法来处理整个事情,但这应该是你想要的
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
另一种方法是重用工作解决方案,即将矩阵转换为适合数据帧使用的字符串。在代码中,这是:
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
的列类型由DataFrame猜测
不相关,但这个答案提醒了我。另一种方法是重用工作解决方案,即将矩阵转换为适合数据帧使用的字符串。在代码中,这是:
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
的列类型由DataFrame猜测
不相关,但这个答案让我想起了
似乎有效并且比@dan getz的答案更快(至少对于这个数据矩阵):)
-
似乎有效并且比@dan getz的答案更快(至少对于这个数据矩阵):)
-
为什么不从电子表格中保存一个csv文件并用csv.read()加载它呢?这应该可以解决。@MichaelK.Borregaard,因为我有一个模型,可以加载多个工作表中的所有设置和数据,我希望避免每次更改时都将它们全部导出到cvs。为什么不从电子表格中保存一个csv文件,并使用csv.read()加载它呢?这应该会解决的。@MichaelK.Borregaard因为我有一个模型,可以加载多个工作表中的所有设置和数据,我希望避免每次更改时都将它们导出到cvs。抱歉,这太糟糕了:joy:@MichaelK.Borregaard很好。。如果您有更好的解决方案…;-)@还有,如果你告诉我是什么或者为什么很糟糕。。我要学习;-)只是因为你滥用了try-catch语法。我仍然认为最好是使用CSV.jl这样的包,使用DataFrames中的内置工具以正确的格式导入数据。如何从电子表格导入数据?@MichaelK.Borregaard我开发了这个模块(它使用python
ezodf
模块)。现在,我将Dan Getz的答案集成到了其中,因此我可以将ods表读取为df=ods\u read(iFile;sheetName=“mySheet”,retType=“DataFrame”)
抱歉,但这太可怕了:joy:@MichaelK.Borregaard well。。如果您有更好的解决方案…;-)@还有,如果你告诉我是什么或者为什么很糟糕。。我要学习;-)只是因为你滥用了try-catch语法。我仍然认为最好是使用CSV.jl这样的包,使用DataFrames中的内置工具以正确的格式导入数据。如何从电子表格导入数据?@MichaelK.Borregaard我开发了这个模块(它使用pythonezodf
模块)。我现在将Dan Getz的答案集成到它上面,这样我就可以把ods表读为df=ods\u read(iFile;sheetName=“mySheet”,retType=“DataFrame”)
我所玩的解决方案是使用writecsv
写入IOBuffer
,然后从中读出来,让它一直在取笑我。这让人想起了这一点,但我认为cleaner.@MichaelK.Borregaard向IOBuffer写入也是这个解决方案的第一个版本(但在去掉尾随标签后编辑成这个版本让我很恼火)。啊-不相关-但是你是如何让readtable
接受IOBuffer
输入的?我可以做a=IOBuffer();writecsv(a,数据矩阵);readcsv(take!(a),DataFrame))
,但我无法让它与CSV一起工作。请阅读或readtable
。谢谢。只要一个音符。。如果在数据矩阵中可能出现nothing
值,人们可以使用s=join([join([(m[i,j]==nothing?NA:m[i,j])在索引(m,2)]中表示j,在索引(m,1)]中表示i,'\t'),'\n')
(时间+10%)来使代码更干净,一个辅助函数沿着这条线getNA(val)=val==nothing?NA:val
会有帮助的。我所玩弄的解决方案是使用writecsv
写入IOBuffer
,然后readtable
,让它一直在取笑我。这让人想起了这一点,但我认为cleaner.@MichaelK.Borregaard向IOBuffer写入也是这个解决方案的第一个版本(但在去掉尾随标签后编辑成这个版本让我很恼火)。啊-不相关-但是你是如何让readtable
接受IOBuffer
输入的?我可以做a=IOBuffer();writecsv(a,数据矩阵);readcsv(take!(a),数据