2010-12-21 93 views
9

前一个问题(Working with heterogenous data in a statically typed language),我问了一下F#如何处理数据分析标准的任务,如操纵非类型化的CSV文件。动态语言擅长于基本任务,如F#类型提供程序和数据处理

data = load('income.csv') 
data.log_income = log(income) 

在F#中,最优雅的方法似乎是问号(?)运算符。不幸的是,在这个过程中,我们失去了静态类型,并且仍然需要类型注释。

一个F#中最令人兴奋的未来功能是Type Providers。以最小的类型安全性损失,CSV类型提供者可以通过动态检查文件来提供类型。

但数据分析通常不会停在那里。我们经常通过一系列的操作来转换数据并创建新的数据集。我的问题是,如果我们主要操纵数据,类型提供程序可以提供帮助吗?例如:

open CSV // Type provider 
let data = CSV(file='income.csv') // Type provider magic (syntax?) 
let log_income = log(data.income) // works! 

这可行,但会污染全局命名空间。考虑添加一列通常更自然,而不是创建一个新变量。有什么方法可以做?

let data.logIncome = log(data.income) // won't work, sadly. 

进行类型供应商提供使用时,我们的目标是创造新的衍生物或清理后的数据集(?)运算符逃生?

也许是这样的:

let newdata = colBind data {logIncome = log(data.income)} // ugly, does it work? 

其他的想法?

回答

6

简短的回答是否定的,长的答案是肯定的(但你不喜欢的结果)。关键要记住的是,F#是一种静态类型语言,句号

对于您提供的代码,newData有哪些类型?如果它不能在编译时被固定下来,那么你需要求助于Obj的铸造。

// newdata MUST have a static type, even if obj 
let newdata = colBind data {logIncome = log(data.income)} 

想象colBind具有以下sinature:

val colBind: Thingey<'a> -> 'b -> Thingey2<'a, 'b> 

这实际上为一个工作方式,但它不会普遍地工作。因为最终你需要一个在编译时不存在的类型。

F#类型提供程序允许您将静态类型数据源自标准编译时环境的外部。但是,类型仍然是静态的。在运行时*无法动态改变这些类型。

*您可以在运行时使用模糊修改对象,如 DynamicObject。但是,一旦 开始沿着这条路走下去,您将失去静态类型 语言的所有优势,如Intellisense。 (这是首先使用F#的主要原因。)

从概念上讲,你想要做的是直截了当。System.Data.DataTable类型已经具有存储表格数据的概念,并具有动态添加列的功能。但由于添加列的类型信息在编译时并不知道,因此存储在这些列中的内容必须被视为Obj并在运行时进行转换。

0

或者,您可以创建'from'和'to'表格,其中表格具有所需的列。这样,您就有了一个类型提供程序使用的静态类型查询和结果模式。