C#读取csv,计算一些东西,导出另一个csv

时间:2014-07-31 07:32:29

标签: c# date csv datatable correlation

我是C#的新手。我想知道如何在C#中以直观的方式进行以下计算。我应该如何阅读输入csv文件以方便所需的计算?我是否将csv读入列表,数组,数据表等?某些单元格中存在空值。由于我是C#的新手,如果您能提供一些示例,我们将不胜感激。谢谢。 :)

输入: 我有一个输入csv文件格式:

<p> // header: date, Y, X1, X2, X3, X4 </p>
<p> // value: yyyy-mm-dd, double, double, double, double, double </p>

所以我有Y和所有X的时间序列数据。对于每个不同的日期,我有很多Y和X行。

数据处理: 我想做以下事情:

  1. 对于每个不同的日期,计算Y和每个X之间的相关性.Y和X的长度可以在不同的日期有所不同。所以每个日期我都会有corr(Y,X1),corr(Y,X2),corr(Y,X3),corr(Y,X4)。

  2. 对于每个不同的日期,排序Y并获得每行的排名,例如

  3. Y等级
         10 1
         50 4
         20 2
         30 3

    获得等级后,它们用于计算单个数量,例如QUANTITY。 (每个不同的日期我将有一个数量的数量。)

    输出: 在所有计算之后,我想将结果导出到另一个格式为:

    的csv文件
    <p> // header: date, corr(Y, X1), corr(Y, X2), corr(Y,X3), corr(Y,X4), QUANTITY </p>
    <p> // value: yyyy-mm-dd, double, double, double, double, double </p>
    

2 个答案:

答案 0 :(得分:1)

好的,到此为止。首先,我使用一个名为CsvHelper的Nuget包来处理你的解析。它非常易于使用和有效。但是出于举例的目的,我只是用逗号分隔每条记录。

我们假设您在路径string path = ...;中有一个包含csv的文件。首先,我们解析CSV。

首先,既然你说可以有空值(虽然CSV解析器可以更好地处理这个),让我们来一个方法。

private static double? getDoubleOrNull(string text)
{
    if(string.IsNullOrWhiteSpace(text))
        return null;
    else
        return double.Parse(text);
}

现在我们可以进行实际的解析并使用该方法。

var records = System.IO.File.ReadAllLines(path)
                            .Skip(1) // the header
                            .Select(c =>
                                       {
                                           var fields = c.Split(',');

                                           return new
                                           {
                                               Date = DateTime.Parse(fields[0]),
                                               Y = getDoubleOrNull(fields[1]),
                                               X1 = getDoubleOrNull(fields[2]),
                                               X2 = getDoubleOrNull(fields[3]),
                                               X3 = getDoubleOrNull(fields[4]),
                                               X4 = getDoubleOrNull(fields[5]),
                                           };
                                       });

完成,好吧,现在我们按日期分组并找到结果。我不确定你想如何关联数据,所以我只假设存在object corr(IEnumerable<double?> Y, IEnumerable<double?> X)函数。我还假设存在object getQuantity(IEnumerable<KeyValuePair<int, double?>> ys),其中键表示您显示的基于1的排名,值表示原始CSV中的Y值。

var result = records.GroupBy(c => c.Date)
                    .Select(c => new
                                 {
                                     Date = c.Key,
                                     corr1 = corr(c.Select(x => x.Y), c.Select(x => x.X1)),
                                     corr2 = corr(c.Select(x => x.Y), c.Select(x => x.X2)),
                                     corr3 = corr(c.Select(x => x.Y), c.Select(x => x.X3)),
                                     corr4 = corr(c.Select(x => x.Y), c.Select(x => x.X4)),
                                     quantity = getQuantity(c => c.OrderBy(x => x).Select((x, index) => new KeyValuePair<int, double>(index + 1, x)))
                                  });

现在,我相信我们应该输出数据。这使得它变得相对简单。

using (StreamWriter writer = new StreamWriter(outputFile))
{
    writer.WriteLine("date, corr(Y, X1), corr(Y, X2), corr(Y,X3), corr(Y,X4), QUANTITY");

    foreach(var v in result)
    {
        writer.WriteLine(string.Join(",", v.Date.ToString("yyyy-MM-dd"), v.corr1, v.corr2, v.corr3, v.corr4, v.quantity));
    }
}

当然,您希望添加大量错误检查。自从我在SO文本编辑器中完成所有这些操作后,我可能已经写了一两个错字,但是从中找出最终解决方案应该很容易。

答案 1 :(得分:0)

我不会尝试发明我自己的CSV解析器 - 当你不得不考虑&#34;逃脱时,做正确的事情是非常困难的。字符串,不同的字段分隔符(&#34 ;;&#34;!)等.pp。

我喜欢kbcsv库,它可以轻松读取csv并提供带有结果的数据表:

http://kbcsv.codeplex.com/