为什么 Deedle 将 DataFrame 布尔列转换为 float 系列?
Why is Deedle casting a DataFrame boolean column into a float Series?
当我 运行 下面的代码时,我得到一个 DataFrame
,其中有一个 bool
列和两个 double
列。但是,当我将 bool
列提取为 Series 时,结果是一个类型为 DateTime
和 float
的 Series 对象。
看起来 Deedle
"cast" 列为另一种类型。
为什么会这样?
open Deedle
let dates =
[ DateTime(2013,1,1);
DateTime(2013,1,4);
DateTime(2013,1,8) ]
let values = [ 10.0; 20.0; 30.0 ]
let values2 = [ 0.0; -1.0; 1.0 ]
let first = Series(dates, values)
let second = Series(dates, values2)
let third: Series<DateTime,bool> = Series.map (fun k v -> v > 0.0) second
let df1 = Frame(["first"; "second"; "third"], [first; second; third])
let sb = df1.["third"]
df1;;
val it : Frame<DateTime,string> =
Deedle.Frame`2[System.DateTime,System.String]
{ColumnCount = 3;
ColumnIndex = Deedle.Indices.Linear.LinearIndex`1[System.String];
ColumnKeys = seq ["first"; "second"; "third"];
ColumnTypes = seq [System.Double; System.Double; System.Boolean];
...
sb;;
val it : Series<DateTime,float> = ...
您可以使用 .GetColumn
将系列提取为布尔值:
let sb':(Series<DateTime,bool>) = df1.GetColumn("third")
//val sb' : Series<DateTime,bool> =
//series [ 2013/01/01 0:00:00 => False; 2013/01/04 0:00:00 => False; 2013/01/08 0:00:00 => True]
至于你问的为什么,我没有查看源代码,但我假设你使用的索引器类型可能是 returns 和 obj
,然后 Deedle 会尝试将其转换为某些东西,或者它可能会尝试将所有内容都转换为 float
。
正如现有答案所指出的那样,GetColumn
是必经之路。调用GetColumn
时可以直接指定泛型参数,避免类型注解,代码更漂亮:
let sb = df1.GetColumn<bool>("third")
Deedle frame 不会静态地跟踪列的类型,因此当您想要将列作为类型化系列获取时,您需要以某种方式指定类型。
我们不想强迫人们编写类型注释,因为它们往往又长又丑,所以获取列的主要方法是 GetColumn
,您可以在其中指定类型参数,如上面的例子。
访问列的其他方法,如 df?third
和 df.["third"]
是假定列类型为 float
的简写,因为这恰好是很常见的情况(至少对于Deedle 在金融领域最常见的用途),因此这两个符号为您提供了一种比 "often works nicely".
更简单的方法
当我 运行 下面的代码时,我得到一个 DataFrame
,其中有一个 bool
列和两个 double
列。但是,当我将 bool
列提取为 Series 时,结果是一个类型为 DateTime
和 float
的 Series 对象。
看起来 Deedle
"cast" 列为另一种类型。
为什么会这样?
open Deedle
let dates =
[ DateTime(2013,1,1);
DateTime(2013,1,4);
DateTime(2013,1,8) ]
let values = [ 10.0; 20.0; 30.0 ]
let values2 = [ 0.0; -1.0; 1.0 ]
let first = Series(dates, values)
let second = Series(dates, values2)
let third: Series<DateTime,bool> = Series.map (fun k v -> v > 0.0) second
let df1 = Frame(["first"; "second"; "third"], [first; second; third])
let sb = df1.["third"]
df1;;
val it : Frame<DateTime,string> =
Deedle.Frame`2[System.DateTime,System.String]
{ColumnCount = 3;
ColumnIndex = Deedle.Indices.Linear.LinearIndex`1[System.String];
ColumnKeys = seq ["first"; "second"; "third"];
ColumnTypes = seq [System.Double; System.Double; System.Boolean];
...
sb;;
val it : Series<DateTime,float> = ...
您可以使用 .GetColumn
将系列提取为布尔值:
let sb':(Series<DateTime,bool>) = df1.GetColumn("third")
//val sb' : Series<DateTime,bool> =
//series [ 2013/01/01 0:00:00 => False; 2013/01/04 0:00:00 => False; 2013/01/08 0:00:00 => True]
至于你问的为什么,我没有查看源代码,但我假设你使用的索引器类型可能是 returns 和 obj
,然后 Deedle 会尝试将其转换为某些东西,或者它可能会尝试将所有内容都转换为 float
。
正如现有答案所指出的那样,GetColumn
是必经之路。调用GetColumn
时可以直接指定泛型参数,避免类型注解,代码更漂亮:
let sb = df1.GetColumn<bool>("third")
Deedle frame 不会静态地跟踪列的类型,因此当您想要将列作为类型化系列获取时,您需要以某种方式指定类型。
我们不想强迫人们编写类型注释,因为它们往往又长又丑,所以获取列的主要方法是 GetColumn
,您可以在其中指定类型参数,如上面的例子。
访问列的其他方法,如 df?third
和 df.["third"]
是假定列类型为 float
的简写,因为这恰好是很常见的情况(至少对于Deedle 在金融领域最常见的用途),因此这两个符号为您提供了一种比 "often works nicely".