我正在尝试使用 Deedle 在 DataFrame 上执行基于行的过程。但我就是无法让我的思想适应 Deedle 的方式。
说一个像这样的框架
Indicator1 Indicator2
1 100 200
2 300 500
3 -200 1000
假设需要对每个指标应用一些规则:
- 如果指标值小于 500 且大于 0,则乘以 1.1
- 如果指标值小于 0,则设为 NaN
我一直在尝试使用Frame.mapRow
....函数。
我知道我可以使用
fun v -> let indVal = v.GetAs<Int>("Indicator1");
let newIndVal = match indVal with
|...... logic
|...... some other logic
let indVal2 = v.GetAs<Int>("Indicator2");
let newIndVal2 = match indVal2 with
|...... logic
|...... some other logic
与Frame.mapRow
....
但我被困在如何使newIndVal
和newIndVal2
回到一行并最终回到一个新的数据框。
我想要实现的是一个框架和框架。另外我只知道一一处理列(在通过索引或名称检索它们之后)。如果要应用的逻辑是通用的,有没有办法不逐列应用逻辑?
使用 C 或 C# 2d 数组执行此操作的命令式(并且非常简单)方法是
loop through the row dimension
loop through the column dimension
apply the rule as the side effect to the array[row,col]
如何在 Deedle 中实现这一点?
更新:
如果计算不需要引用同一行的其他列,Leaf Garland 的建议非常有效。就我而言,我需要逐行查看数据,因此我想使用 Frame.mapRows。我应该对简化的要求很清楚:
说一个像这样的框架
Indicator1 Indicator2
1 100 200
2 <Missing> 500
3 -200 1000
4 100 <Missing>
5 <Missing> 500
6 -200 100
例如,如果指标 1 小于 300,则指标 2 的新值为指标 2 + 5% * 指标 1
我需要使用
mapRows fun k v -> let var1 = v.get("Indicator1")
let var2 = v.get("Indicator2")
run through the conditions and produce new var1 and var2
produce a objectSeries
|> Frame.ofRows
上面的伪代码听起来很简单,但我只能弄清楚如何重现正确的 objectSeries 来重新创建 Frame。
我还注意到一些我无法用 mapRows 函数解释的东西 [SO question]:Deedle Frame.mapRows 如何正确使用它以及如何正确构建对象系列
更新
自从发布了原始问题以来,我就在 C# 中使用了 Deedle。令我惊讶的是,在 C# 中基于行的计算非常简单,并且 C# Frame.rows 函数处理缺失值的方式与 F# mapRows 函数非常不同。以下是我用来尝试验证逻辑的一个非常基本的示例。它可能对任何正在搜索类似应用程序的人有用:
需要注意的是: 1. rows 函数没有删除行,而两列的值都丢失了 2. mean 函数足够聪明,可以根据可用数据点计算平均值。
using System.Text;
using System.Threading.Tasks;
using Deedle;
namespace TestDeedleRowProcessWithMissingValues
{
class Program
{
static void Main(string[] args)
{
var s1 = new SeriesBuilder<DateTime, double>(){
{DateTime.Today.Date.AddDays(-5),10.0},
{DateTime.Today.Date.AddDays(-4),9.0},
{DateTime.Today.Date.AddDays(-3),8.0},
{DateTime.Today.Date.AddDays(-2),double.NaN},
{DateTime.Today.Date.AddDays(-1),6.0},
{DateTime.Today.Date.AddDays(-0),5.0}
}.Series;
var s2 = new SeriesBuilder<DateTime, double>(){
{DateTime.Today.Date.AddDays(-5),10.0},
{DateTime.Today.Date.AddDays(-4),double.NaN},
{DateTime.Today.Date.AddDays(-3),8.0},
{DateTime.Today.Date.AddDays(-2),double.NaN},
{DateTime.Today.Date.AddDays(-1),6.0}
}.Series;
var f = Frame.FromColumns(new KeyValuePair<string, Series<DateTime, double>>[] {
KeyValue.Create("s1",s1),
KeyValue.Create("s2",s2)
});
s1.Print();
f.Print();
f.Rows.Select(kvp => kvp.Value).Print();
// 29/05/2015 12:00:00 AM -> series [ s1 => 10; s2 => 10]
// 30/05/2015 12:00:00 AM -> series [ s1 => 9; s2 => <missing>]
// 31/05/2015 12:00:00 AM -> series [ s1 => 8; s2 => 8]
// 1/06/2015 12:00:00 AM -> series [ s1 => <missing>; s2 => <missing>]
// 2/06/2015 12:00:00 AM -> series [ s1 => 6; s2 => 6]
// 3/06/2015 12:00:00 AM -> series [ s1 => 5; s2 => <missing>]
f.Rows.Select(kvp => kvp.Value.As<double>().Mean()).Print();
// 29/05/2015 12:00:00 AM -> 10
// 30/05/2015 12:00:00 AM -> 9
// 31/05/2015 12:00:00 AM -> 8
// 1/06/2015 12:00:00 AM -> <missing>
// 2/06/2015 12:00:00 AM -> 6
// 3/06/2015 12:00:00 AM -> 5
//Console.ReadLine();
}
}
}