寻找更智能的方式读取和写入时间序列数据 [英] Looking for Smarter way to read and write time series data

查看:80
本文介绍了寻找更智能的方式读取和写入时间序列数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

你好朋友,
我是这个论坛和C#编程的新手.我自己教过一点C#.
我正在这个小应用程序中工作,其中有一个带有
的winForm -组合框(cb值为0,1,2 ..... 25)和
-一个dataGridView. dataGridView列是根据用户选择的值填充的(直到运行时我才知道).用户将数据复制并粘贴到dataGridView中,如下所示:

Hello Friends,
I am a totally newbie to this forum and to C# programming as well. Taught little bit of C# myself.
I am working in this little application where I have a winForm with
- a combobox (with cb values 0,1,2.....25) and
- a dataGridView. The dataGridView columns are populated based on the value selected by the user (which I won''t know until runtime). User copies and pastes data into the dataGridView which will look something like this:

col1   col2   col3   col4   col4   col 5   col6   ........col30
----------------------------------------------------------- 
2001    08    25    14    35    0.00    0.00
2001    08    25    14    40    0.00    0.00
2001    08    25    14    45    0.00    0.00
2001    08    25    14    50    0.00    0.00
2001    08    25    14    55    0.00    0.00
2001    08    25    15    00    0.00    0.00
2001    08    25    15    05    0.00    0.00
2001    08    25    15    10    0.00    0.00
2001    08    25    15    15    0.00    0.00
2001    08    25    15    20    0.00    0.00
2001    08    25    15    25    0.00    0.00
2001    08    25    15    30    0.00    0.10
2001    08    25    15    35    0.15    0.00
2001    08    25    15    40    0.30    0.00
2001    08    25    15    45    0.20    0.00
2001    08    25    15    50    0.10    0.00
2001    08    25    15    55    0.00    0.00
2001    08    25    16    00    0.00    0.00
2001    08    25    16    05    0.00    0.90
2001    08    25    16    10    0.00    0.00
2001    08    25    16    15    0.00    0.00



因此,前5列始终显示着年,月,日,小时和分钟(因此我将其称为日期列").除此之外,其他列将具有我需要处理的值(我称它们为值列").

阅读正在进行...我将稍后发布代码(我怀疑自己是用聪明的方式完成的:-))

现在,
我需要摆脱在每个值列"(第6列及以后的列)中具有零值的行...如果我有5个值列"并且这些列中的每一个都具有0个值,然后删除该行.但是,如果该行中的任何值列"具有非零值,则不要删除.
-
这是另一个条件:
-
在两个非零块之间,有一个由用户定义的最小时间间隔.例如,如果用户选择间隔时间为2小时,那么如果该行距其上方的非零行2小时以内,则我将使行保持全零值.

结果谁看起来像这样:



So the first 5 columns are always there which read year, month, day, hour and minutes(so I call them ''date columns''). Beyond that, other column(s) will have the value I need to work on (and I call them ''value columns'').

Reading is working... I will post the code in a bit (I doubt I am doing it in smart way :-) )

NOW,
I need to get rid of rows that have zero values in each of the ''value columns'' (column6 and beyond)... meaining if I have 5 ''value columns'' and if each of these columns have 0 values, then delete that row. But do not delete if any one of the ''value columns'' has a non-zero value on that row.
-
Here is another condition:
-
Between two non-zero blocks there is a minimum time separation defined by the user. For eg if the user selects the separation time as 2 hours then I will need to keep the rows even with all zero values if that row is within 2 hours from a non-zero row above it.

The result whould look like this:

2001    08    25    15    25    0.00    0.00
2001    08    25    15    30    0.00    0.10
2001    08    25    15    35    0.15    0.00
2001    08    25    15    40    0.30    0.00
2001    08    25    15    45    0.20    0.00
2001    08    25    15    50    0.10    0.00
2001    08    25    15    55    0.00    0.00
2001    08    25    16    00    0.00    0.00
2001    08    25    16    05    0.00    0.90
2001    08    25    16    10    0.00    0.00



这是我读取数据的方式:



Here is how I am reading the data:

//Read Year Month, Day Hour and Minute and store them as date in an array
            DateTime[] dt = new DateTime[this.dataGridView1.Rows.Count-1];
            DataTable gageValues = new DataTable();
            int i = 0;
            foreach (DataGridViewRow row in dataGridView1.Rows)
            {
                if (row.Cells[0].Value != null)
                

                    String mth = row.Cells[1].Value.ToString() + "/";
                    String dy = row.Cells[2].Value.ToString() + " ";
                    String hr = row.Cells[3].Value.ToString() + ":";
                    String min = row.Cells[4].Value.ToString();
                    if (mth.Length == 1)
                    {
                        mth = "0" + mth;
                    }
                    if (dy.Length == 1)
                    {
                        dy = "0" + dy;
                    }
                    if (hr.Length == 1)
                    {
                        hr = "0" + hr;
                    }
                    if (min.Length == 1)
                    {
                        min = "0" + min;
                    }
                    string dts = yr + mth + dy + hr + min;
                    dt[i] = Convert.ToDateTime(dts);
                    i++;
                }
            }
            // Add the raingage values to the datatable-gageValues
            this._dataArray.Clear();
                    for(int jj=5; jj<ngag+5; jj++)
                    {
                        _dataArray.Add(new double[this.dataGridView1.Rows.Count - 1]);
                        for(int ii=0;ii<this.dataGridView1.Rows.Count-1;ii++)
                        {
                           _dataArray[jj-5][ii]=double.Parse(this.dataGridView1.Rows[ii].Cells[jj].Value.ToString());
                        }
                    }
            List<object> objectNumbers = new List<object>();
            gageValues.Columns.Add("DateTime");
            foreach (DateTime dttm in dt)
            {
                objectNumbers.Add((object)dttm);
                gageValues.Rows.Add();
                for (int a = 0; a < objectNumbers.Count - 5; a++)
                {
                    gageValues.Rows[a][0] = objectNumbers[a];
                }

            }
            objectNumbers.Clear();

            for (int ii = 0; ii < this._dataArray.Count; ii++)
            {
                string gageNames = this._names[ii];
                gageValues.Columns.Add(gageNames);
                
                foreach (double number in this._dataArray[ii])
                {
                    objectNumbers.Add((object)number);
                }

                while (gageValues.Rows.Count < objectNumbers.Count)
                {
                    gageValues.Rows.Add();
                }

                for (int a = 0; a < objectNumbers.Count; a++)
                {
                    gageValues.Rows[a][ii+1] = objectNumbers[a];
                }
                objectNumbers.Clear();

            }



然后我在每一行中添加值以检查总和是否为零,这有助于我找出哪些行全为零



Then I add values in each row to check if the sum is zero which helps me figure out which rows have all zeros

double[] sumrow = new double[gageValues.Rows.Count];
           int count = -1;
           foreach (DataRow dr in gageValues.Rows)
           {
               count = count + 1;
               double sum = 0;
               for(int j=1; j<gageValues.Columns.Count;j++)
               {
                   sum = double.Parse(dr[j].ToString()) + sum;
               }
               sumrow[count] = sum;
           }


现在,我尝试分析此sumrow []数组以隔离数据的非零块,但无法找出更好的逻辑.我们将不胜感激.


Now I am trying to analyze this sumrow[] array to isolate the non-zero blocks of the data but could not figure out a better logic. Any help will be greatly appreciated.

推荐答案

SA可能是正确的,尽管我希望首先更详细地了解您的数据.

我还建议其中一些是非常非常不必要的:
SA may be right, though I would want to see your data in more detail first.

I would also suggest that some of this is very, very unnecessary:
String mth = row.Cells[1].Value.ToString() + "/";
String dy = row.Cells[2].Value.ToString() + " ";
String hr = row.Cells[3].Value.ToString() + ":";
String min = row.Cells[4].Value.ToString();
if (mth.Length == 1)
{
    mth = "0" + mth;
}
if (dy.Length == 1)
{
    dy = "0" + dy;
}
if (hr.Length == 1)
{
    hr = "0" + hr;
}
if (min.Length == 1)
{
    min = "0" + min;
}
string dts = yr + mth + dy + hr + min;
dt[i] = Convert.ToDateTime(dts);

可以替换为:

Could be replaced with:

dt[i] = new DateTime(yr,
                     row.Cells[1].Value, //Month
                     row.Cells[2].Value, //Day
                     row.Cells[3].Value, //Hour
                     row.Cells[4].Value);//Minute

我认为您需要查看如何处理所有这一切:我特别不喜欢代码中混有+5和-5-我知道您这样做的原因,但是很难理解和维护. br/> 不要使用List<object>-具体来说,它有助于避免出现问题,这意味着您无需先投射它就可以使用它!

老实说,我将使用一个采用DataGridViewRow的构造函数和一个ContainsInformaion属性getter来设置一个类(称为DatedValues)来保存行数据.如果为true,则将添加该行,否则将其丢弃.该类将具有(例如)一个DateTime属性和一个值列表.然后使用带信息的DatedValues列表代替您的List<Object>-这将使您的代码更加清晰!


"感谢OriginalGriff的回复.
设置课程听起来是一种更好的方法.我最初计划只包含一个值列,然后以这种方式开始,但后来决定添加更多的值列.
我仍然无法弄清楚如何隔离数据中的非零块.对我而言,最难的部分是照顾两个非零块之间的最小间隔.我可以将原始数据,目标结果和规则发送给您...但是我找不到在此处附加任何文件的方法"


您的从非零开始的两个小时"状态应该不会成为太大的问题:将日志时间作为DateTime后,您可以使用DateTime.AddHours或DateTime.AddMinutes方法.请记住,您可以在两个DateTime对象之间进行直接比较:

I think you need to look at how you are handling all this: I particularly dislike the +5 and -5 your code is sprinkled with - I know why you are doing it, but it is hard to understand and maintain.
Don''t use List<object> - be specific, it helps to avoid problems and means you don''t have to cast it before you can use it!

To be honest, I would set up a class (call it DatedValues)to hold row data with a constructor taking a DataGridViewRow and with a ContainsInformaion property getter. If true, I would add the row, otherwise I would discard it. The class would have (say) a DateTime property, and a List of values. Then use a list of the with-information DatedValues instead of your List<Object> - it will make your code a lot clearer!


"Thanks OriginalGriff for your response.
Setting up a class sounds like a better way to do this. I initially planned on having only one value column and started this way but later decided to add more value columns.
I still cannot figure out how I isolate the non-zero blocks in my data. The hardest part for me is to take care of minimum separation between two non-zero blocks. I can send you my original data, targetted result and the rules... but I could not find a way to attach any file here"


Your "two hours since a non-zero" condition shouldn''t be too major a problem: once you have the log time as a DateTime, you can set a "always include if before this" DateTime by using the DateTime.AddHours or DateTime.AddMinutes methods. Remember, you can do direct comparisons between two DateTime objects:

DateTime now = DateTime.Now;
DateTime then = now.AddMinutes(120);
...
if (myRecord.Timestamp <= then)
   {
   ...
   }


我有一种强烈的感觉,您认为零数据不应该为零.您是否尝试过读取零以表示无效数据或无数据"?那是错误的.例如,您应该使用double.NaN的值.

—SA
I have a strong feeling that you zero data is not supposed to be zero. Did you try to read zeroes to denote invalid data or "no data"? That would be wrong. You should use, for example, the values of double.NaN.

—SA


这篇关于寻找更智能的方式读取和写入时间序列数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆