Dataframe 如何在Julia中将IndexedTable转换为数据帧?
在快速解释工作中,Dataframe 如何在Julia中将IndexedTable转换为数据帧?,dataframe,type-conversion,julia,Dataframe,Type Conversion,Julia,在快速解释工作中,IndexedTables处理单个元素(例如选择或“更新”)似乎比DataFrames快得多,但是DataFrames具有更好的功能生态系统,例如绘图、导出 因此,在工作流的某一点上,我想将IndexedTable转换为数据帧,例如 using DataFrames, IndexedTables, IndexedTables.Table tn = Table( Columns( param = String["price","price","pric
IndexedTables
处理单个元素(例如选择或“更新”)似乎比DataFrames
快得多,但是DataFrames
具有更好的功能生态系统,例如绘图、导出
因此,在工作流的某一点上,我想将IndexedTable转换为数据帧,例如
using DataFrames, IndexedTables, IndexedTables.Table
tn = Table(
Columns(
param = String["price","price","price","price","waterContent","waterContent"],
item = String["banana","banana","apple","apple","banana", "apple"],
region = Union{String,DataArrays.NAtype}["FR","UK","FR","UK",NA,NA]
),
Columns(
value2000 = Float64[2.8,2.7,1.1,0.8,0.2,0.7],
value2010 = Float64[3.2,2.9,1.2,0.8,0.2,0.8],
)
)
至>>
或
至>>
我可以找到各个“行”值在表上与pair()
交互:
然而,我无法获得列的名称和类型,我想按列工作会更有效率
编辑:我确实用上面的代码获得了“column”类型,现在我只需要获得列名,如果有的话:
colTypes = Union{Union,DataType}[]
for item in tn.index.columns
push!(colTypes, eltype(item))
end
for item in tn.data.columns
push!(colTypes, eltype(item))
end
EDIT2:根据要求,这是一个IndexedTable示例,使用(当前)Dan Getz answer无法转换列名,因为“索引”列命名为元组,“数据”列为正常元组:
t_named_idx = Table(
Columns(
param = String["price","price","price","price","waterContent","waterContent"],
item = String["banana","banana","apple","apple","banana", "apple"],
region = Union{String,DataArrays.NAtype}["FR","UK","FR","UK",NA,NA]
),
Columns(
Float64[2.8,2.7,1.1,0.8,0.2,0.7],
)
)
问题似乎出现在可索引的API中,特别是在不区分索引和值的columns(t)
函数中。丑陋、快速和肮脏的“解决方案”(我希望它在其他方面是可行的):
julia>df=DataFrame(
permutedims(#这里它是编写转换函数的初始附件。它保留列名和类型。如果它可以作为convert(DataFrame,t::IndexedArray)
在DataFrame或IndexedTable包中进行清理和实现,那就太好了
以下转换功能:
toDataFrame(cols::Tuple, prefix="x") =
DataFrame(;(Symbol("$prefix$c") => cols[c] for c in fieldnames(cols))...)
toDataFrame(cols::NamedTuples.NamedTuple, prefix="x") =
DataFrame(;(c => cols[c] for c in fieldnames(cols))...)
toDataFrame(t::IndexedTable) = toDataFrame(columns(t))
给出(在问题中定义了tn
和t
的Julia 0.6上):
类型信息大部分被保留:
julia> typeof(df_tn[:,1])
DataArrays.DataArray{String,1}
julia> typeof(df_tn[:,4])
DataArrays.DataArray{Float64,1}
对于未命名列:
julia> t
───────────────────────────────┬─────────
"price" "apple" "FR" │ 1.1 1.2
"price" "apple" "UK" │ 0.8 0.8
"price" "banana" "FR" │ 2.8 3.2
"price" "banana" "UK" │ 2.7 2.9
"waterContent" "apple" NA │ 0.7 0.8
"waterContent" "banana" NA │ 0.2 0.2
julia> df_t = toDataFrame(t)
6×5 DataFrames.DataFrame
│ Row │ x1 │ x2 │ x3 │ x4 │ x5 │
├─────┼────────────────┼──────────┼──────┼─────┼─────┤
│ 1 │ "price" │ "apple" │ "FR" │ 1.1 │ 1.2 │
│ 2 │ "price" │ "apple" │ "UK" │ 0.8 │ 0.8 │
│ 3 │ "price" │ "banana" │ "FR" │ 2.8 │ 3.2 │
│ 4 │ "price" │ "banana" │ "UK" │ 2.7 │ 2.9 │
│ 5 │ "waterContent" │ "apple" │ NA │ 0.7 │ 0.8 │
│ 6 │ "waterContent" │ "banana" │ NA │ 0.2 │ 0.2 │
编辑:@Antonello指出,混合命名元组和未命名元组的大小写处理不正确。要正确处理,我们可以定义:
toDataFrame(t::IndexedTable) =
hcat(toDataFrame(columns(keys(t)),"y"),toDataFrame(columns(values(t))))
然后,混合情况给出如下结果:
julia> toDataFrame(tn2)
6×5 DataFrames.DataFrame
│ Row │ param │ item │ region │ x1 │ x2 │
├─────┼────────────────┼──────────┼────────┼─────┼─────┤
│ 1 │ "price" │ "apple" │ "FR" │ 1.1 │ 1.2 │
│ 2 │ "price" │ "apple" │ "UK" │ 0.8 │ 0.8 │
│ 3 │ "price" │ "banana" │ "FR" │ 2.8 │ 3.2 │
│ 4 │ "price" │ "banana" │ "UK" │ 2.7 │ 2.9 │
│ 5 │ "waterContent" │ "apple" │ NA │ 0.7 │ 0.8 │
│ 6 │ "waterContent" │ "banana" │ NA │ 0.2 │ 0.2 │
只需安装iTerablables,然后
using IterableTables
df = DataFrames.DataFrame(it)
谢谢..我正在“研究”它..事实上,转换后的df由任何列组成,它不存储最终的列名..Dan的解决方案似乎很好。你测试过了吗?如果数据是向量,是否有问题?顺便说一句,我们有可能会有“胶水”请参阅:@Liso Ok,我尝试了一下,Dan Gets的解决方案效果很好(对于大型数据集也是微秒级),除非只有一个{index,data}是一个名为元组的,所有列都被转换为席名。你可以添加一个小的例子,它不与列名一起工作吗?@利索补充说……我的丑陋的解决方案仍然适用于所有情况……但它很丑陋;-(而且丹得到的回答速度慢)它比我的解决方案工作得快(对于大数据集来说,微秒也是如此)显然要优雅得多,但当只有{index,data}中的一个是一个NamedTuple,所有列都被转换成席名字。一般来说,这个答案告诉我们,最好是看一个模块的API,而不是尝试用它的内部来抛出一个对象。我注意到混合命名和非命名元组的问题,事实上,这个解决方案的早期迭代处理得很好。调整了一点来处理它。我来看看。在答案中添加了一个编辑来处理混合的情况。效果很好(除了在那里复制/粘贴似乎是一个感谢。很遗憾,“胶水包”的问题由@Liso链接的问题还没有解决,否则这应该真的解决..摆脱了恼人的不可见字符。很高兴听到IterableTables(和require.jl!),但它只在源代码可还原为命名元组时才会转换。在我的示例中,它可以与tn
一起使用,但不能(至少在没有初步转换的情况下)使用t
。
# NDSparse creation...
content = [["banana","banana","apple","apple","orange"],["us",missing,"us","eu","us"],[1.1,2.2,3.3,missing,5.5]]
dimNames = ["item","region"]
t = NDSparse(content...,names=Symbol.(dimNames))
# NDSparse conversion to df...
names = vcat(keys(keys(t)[1])...,:value)
cols = columns(t)
df = DataFrame(map((n,v) -> Pair(n,v), names, cols))
toDataFrame(cols::Tuple, prefix="x") =
DataFrame(;(Symbol("$prefix$c") => cols[c] for c in fieldnames(cols))...)
toDataFrame(cols::NamedTuples.NamedTuple, prefix="x") =
DataFrame(;(c => cols[c] for c in fieldnames(cols))...)
toDataFrame(t::IndexedTable) = toDataFrame(columns(t))
julia> tn
param item region │ value2000 value2010
─────────────────────────────────┼─────────────────────
"price" "apple" "FR" │ 1.1 1.2
"price" "apple" "UK" │ 0.8 0.8
"price" "banana" "FR" │ 2.8 3.2
"price" "banana" "UK" │ 2.7 2.9
"waterContent" "apple" NA │ 0.7 0.8
"waterContent" "banana" NA │ 0.2 0.2
julia> df_tn = toDataFrame(tn)
6×5 DataFrames.DataFrame
│ Row │ param │ item │ region │ value2000 │ value2010 │
├─────┼────────────────┼──────────┼────────┼───────────┼───────────┤
│ 1 │ "price" │ "apple" │ "FR" │ 1.1 │ 1.2 │
│ 2 │ "price" │ "apple" │ "UK" │ 0.8 │ 0.8 │
│ 3 │ "price" │ "banana" │ "FR" │ 2.8 │ 3.2 │
│ 4 │ "price" │ "banana" │ "UK" │ 2.7 │ 2.9 │
│ 5 │ "waterContent" │ "apple" │ NA │ 0.7 │ 0.8 │
│ 6 │ "waterContent" │ "banana" │ NA │ 0.2 │ 0.2 │
julia> typeof(df_tn[:,1])
DataArrays.DataArray{String,1}
julia> typeof(df_tn[:,4])
DataArrays.DataArray{Float64,1}
julia> t
───────────────────────────────┬─────────
"price" "apple" "FR" │ 1.1 1.2
"price" "apple" "UK" │ 0.8 0.8
"price" "banana" "FR" │ 2.8 3.2
"price" "banana" "UK" │ 2.7 2.9
"waterContent" "apple" NA │ 0.7 0.8
"waterContent" "banana" NA │ 0.2 0.2
julia> df_t = toDataFrame(t)
6×5 DataFrames.DataFrame
│ Row │ x1 │ x2 │ x3 │ x4 │ x5 │
├─────┼────────────────┼──────────┼──────┼─────┼─────┤
│ 1 │ "price" │ "apple" │ "FR" │ 1.1 │ 1.2 │
│ 2 │ "price" │ "apple" │ "UK" │ 0.8 │ 0.8 │
│ 3 │ "price" │ "banana" │ "FR" │ 2.8 │ 3.2 │
│ 4 │ "price" │ "banana" │ "UK" │ 2.7 │ 2.9 │
│ 5 │ "waterContent" │ "apple" │ NA │ 0.7 │ 0.8 │
│ 6 │ "waterContent" │ "banana" │ NA │ 0.2 │ 0.2 │
toDataFrame(t::IndexedTable) =
hcat(toDataFrame(columns(keys(t)),"y"),toDataFrame(columns(values(t))))
julia> toDataFrame(tn2)
6×5 DataFrames.DataFrame
│ Row │ param │ item │ region │ x1 │ x2 │
├─────┼────────────────┼──────────┼────────┼─────┼─────┤
│ 1 │ "price" │ "apple" │ "FR" │ 1.1 │ 1.2 │
│ 2 │ "price" │ "apple" │ "UK" │ 0.8 │ 0.8 │
│ 3 │ "price" │ "banana" │ "FR" │ 2.8 │ 3.2 │
│ 4 │ "price" │ "banana" │ "UK" │ 2.7 │ 2.9 │
│ 5 │ "waterContent" │ "apple" │ NA │ 0.7 │ 0.8 │
│ 6 │ "waterContent" │ "banana" │ NA │ 0.2 │ 0.2 │
using IterableTables
df = DataFrames.DataFrame(it)