Cómo convertir una matriz de tipo mixto a DataFrame en Julia reconociendo los tipos de columna
Una buena característica de DataFrames es que puede almacenar columnas con diferentes tipos y puede "reconocerlas automáticamente", por ejemplo:
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}
Sin embargo, cuando intento alcanzar el mismo resultado a partir de una Matriz (importada de una hoja de cálculo) "pierdo" esa conversión automática:
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}
Hay varias preguntas sobre S.O. sobre cómo convertir una matriz a un marco de datos (p. ej.DataFrame de matriz con encabezado, Convertir matriz de Julia a trama de datos), pero ninguna de las respuestas allí trata con la conversión de una matriz de tipo mixto.
¿Cómo podría crear un DataFrame a partir de una matriz que reconozca automáticamente el tipo de las columnas?
EDITAR: Icomparó las tres soluciones: (1) convierte el df (usando el diccionario o el constructor de matrices ... primero es más rápido) y luego aplica try-catch para la conversión de tipos (mi respuesta original); (2) convertir a cadena y luego usar df.inlinetable (respuesta de Dan Getz); (3) verifique el tipo de cada elemento y su consistencia en columnas (respuesta de Alexander Morley).
Estos son los resultados:
# 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)
Por lo tanto, es una locura, la solución más eficiente parece "verter el agua" y reducir el problema a uno ya resuelto ;-)
Gracias por todas las respuestas.