当 DataFrame 是另一个结构体的组件时,如何将测试数据加载到 Julia DataFrame 中

问题描述 投票:0回答:1

我在 Julia 中创建了一个类型(结构)。

struct ExampleStruct
    data::DataFrame
end

它有一些相关的函数/方法,我想为其编写单元测试。

这是一个弥补测试的示例。

function has_names(df)
    return length(names(df)) > 0
end

我有点被两个问题困扰。

  • 该类型需要一个构造函数
  • 测试需要一种方法来用一些测试数据来初始化对象

这是我打算用于测试的数据。

test_data = [
    ["col1", "col2", "col3"],
    ["1", "2", "3"],
    ["1a", "2a" "3a"],
    ["1b", "2b" "3b"],
]

如果我直接测试

DataFrame
,我可以使用以下构造函数来初始化它。

example_df = DataFrame(test_data[2:end, :], Symbol.(test_data[1, :]))

但是由于

DataFrame
包含在结构
ExampleStruct
中,因此
ExampleStruct
构造函数需要某种方式来接受这种类型的数据并将其传递给
DataFrame
构造函数。 (可能吧。)

# inner constructor
function ExampleStruct( arg? )
    data(arg) # ?
end

# outer constructor
function ExampleStruct( test_data? )
    ExampleStruct(test_data) # calling the inner constructor here??
end

当不运行单元测试,但运行正常代码时,将从文件加载数据。可能有多种可能的文件格式,其中之一是 CSV。

因此,在“正常”(不是测试)代码中,

ExampleStruct
的构造函数应该执行类似的操作来初始化
data

# elsewhere, but could be a different file type as well
#using CSV
#csvfile = CSV.File(filename)
# 

data = DataFrame(csvfile)

这里“缺失的一块拼图”是

ExampleStruct
的构造函数。 (我想。)我不知道如何写。 (从我为上面的“内部”和“外部构造函数”提供的草图代码中这可能是显而易见的。)

我认为它需要两种方法,因为它需要处理两种情况。

  • 存在从一些预先确定的数据初始化
    DataFrame
    数据的情况。这用于测试。在本例中,我使用
    Vector{Vector{String}}
    来存储数据,但如果其他类型更容易使用,也可以是其他类型。 (使用
    Vector{Vector{T}}
    时很难定义列名称。)
  • 然后是从某种文件格式初始化
    DataFrame
    的情况。它可能是
    CSV.File
    也可能是其他格式。我猜想有一种方法可以使用抽象类型来表达这一点,抽象类型是所有可能的文件类型的联合。我对 Julia 不太了解 - 这只是我通过阅读文档对它如何工作的感觉。

我希望这个问题有意义。我才刚刚开始与 Julia 合作,所以目前这一切都超出了我的知识范围。

如果我用 Python 来做这件事,我可能会写这样的东西:

class ExampleStruct:
    def __init__(self, arg):
        if isinstance(arg, list):
            self.data = DataFrame(arg[1:], cols=arg[0])
        else:
            # assume arg is some kind of file object, init from this

以上内容应视为伪代码。更好的设计可能是使用

kwargs
而不是检查
arg
的类型。

dataframe julia
1个回答
0
投票

您的问题实际上是关于如何将一个结构封装在另一个数据结构中,这对于任何具有对象能力的语言来说都是基础。本质上,您可以寻址您选择在结构中调用

data
的 DataFrame 成员:

struct ExampleStruct
    data::DataFrame
end

用“.”运算符,因此如果

examp
ExampleStruct
,则其
DataFrame
成员将作为
examp.data
进行访问。

请参阅 https://docs.julialang.org/en/v1/manual/types/#Composite-Types。您给出了一个 Python 示例,Python 类是相似的,尽管它们通常不在声明中键入结构成员,并且许多 Python 类通过使用而不是显式声明其成员的事实可能使您无法学习这一点:(。

所以你有例如:

using CSV
using DataFrames

struct ExampleStruct
    data::DataFrame
end

function has_names(df::DataFrame)
    return length(names(df)) > 0
end
has_names(examplestruct::ExampleStruct) = has_names(examplestruct.data)

# here we give a Matrix rather than the vector of vectors you did
test_data = [
    "col1" "col2" "col3";
    "1" "2" "3";
    "1a"  "2a"  "3a";
    "1b" "2b" "3b";
]


example_df = DataFrame(test_data[2:end, :], Symbol.(test_data[1, :]))

打印

testexample = ExampleStruct(3×3 DataFrame
 Row │ col1    col2    col3
     │ String  String  String
─────┼────────────────────────
   1 │ 1       2       3
   2 │ 1a      2a      3a
   3 │ 1b      2b      3b)
has_names(testexample) = true

.

© www.soinside.com 2019 - 2024. All rights reserved.