【问题标题】:Count the frequency of each elements in a DataGridView in .Net Windows Application Form计算 .Net Windows 应用程序窗体中 DataGridView 中每个元素的频率
【发布时间】:2021-06-21 01:28:39
【问题描述】:

我有一些从 csv 文件读入 DataGridViews 的数据集,我需要绘制一些图表,在其中计算每列中每个不同变量的频率。
我找到了一个code,它计算数组元素的频率然后打印它们,我尝试在我的数据网格上使用相同的逻辑。
我从一个只有 2 个值(2.01.0)的列(“SEX”列)开始,但是当我尝试查看计数结果时,我总是得到 1(这意味着它没有计算事物)。它应该显示在列中找到的最后一个不同值的计数(在我的例子中是 2.0,它出现了 140 次)。

编辑:我尝试将计数结果附加到文本框,我看到每个循环都得到1,而我应该只得到2个值(这是计数2.0然后是计数1.0)

我还需要绘制输出,所以我猜我可以使用字典来存储变量名 + 频率。

public void countFreq() //function to count the frequency of each var in a column -not working yet-
        {
            var n = dataGridView1.RowCount;

            var visited = new bool[n];

            // Traverse through array elements and
            // count frequencies
            for (var i = 0; i < n; i++)
            {
                // Skip this element if already processed
                if (visited[i] || dataGridView1.Rows[i].Cells["SEX"].Value
                    == null)
                    continue;
                // Count frequency
                var count = 1;
                for (var j = i + 1; j < n; j++)
                    if (dataGridView1.Rows[i].Cells["SEX"].Value == dataGridView1.Rows[j].Cells["SEX"].Value)
                    {
                        visited[j] = true;
                        count++;
                    }

                textFile.Text += count.ToString(); //for testing purposes I used a textfield to print the last count value
            }
        }

我知道对于值是显式的列,我可以在我的数据网格行上循环并使用计数方法(我这样做了),但是对于我的大多数数据,我没有明确知道每一行中的值,所以我需要找到一种方法来做到这一点。

【问题讨论】:

  • 很难理解您遇到了什么问题以及您要计算什么。我不知道发布的代码应该做什么。您是否要获取性别列中 1 和 2 的数量?
  • @JohnG 是的,我以 1 和 2 为例,但我希望在我的数据网格中的给定列中找到每个不同值的频率。这些值通常是未知的,所以我可以使用类似if (dataGridView1.Rows[i].Cells["SEX"].Value.ToString() == "1.0") count++;
  • 我建议使用Dictionary,其中找到的值是键,值是计数。
  • @JohnG 问题是我不知道在某些列中可以找到什么值,所以我不能在那里明确使用这个条件,即if (dataGridView1.Rows[i].Cells["RandomColumn"].Value.ToString() == "RandomValue") 而我在这里尝试的解决方案没有似乎不像它应该的那样工作
  • 我没有听懂你的意思。除了在该列中找到每个“不同”值的次数之外,您是否还试图查找列中的所有“不同”值?

标签: c# .net visual-studio winforms


【解决方案1】:

我不确定这是否是您正在寻找的。此外,下面的代码循环遍历网格中的行,但是,如果网格有数据源,我建议循环通过该集合而不是网格行。

下面是一个采用列索引并返回Dictionary&lt;string, int&gt; 的方法。一个简单的循环遍历给定列中的每个单元格,如果单元格的 Value 不在字典中,我们将添加它。如果单元格值已经在字典中,将简单地增加它的intValue。循环结束后,返回字典。像……

private Dictionary<string, int> GetCountOfValues(string columnName) {
  string curKey = "";
  Dictionary<string, int> valuesAndCounts = new Dictionary<string, int>();
  foreach (DataGridViewRow row in dataGridView1.Rows) {
    if (!row.IsNewRow) {
      if (row.Cells[columnName].Value != null) {
        curKey = row.Cells[columnName].Value.ToString();
        if (valuesAndCounts.ContainsKey(curKey)) {
          valuesAndCounts[curKey]++;
        }
        else {
          valuesAndCounts.Add(curKey, 1);
        }
      }
    }
  }
  return valuesAndCounts;
}

用法可能看起来像……

Dictionary<string, int> column0Counts = GetCountOfValues("Col0");
Dictionary<string, int> column1Counts = GetCountOfValues("Date");

【讨论】:

  • 这正是我所需要的,我非常感谢您的帮助。如果有一天有人需要它,只是为了完成这个,如果你想打印这些对,你可以使用这样的东西foreach (KeyValuePair&lt;string, int&gt; kvp in column0Counts) { textFile.Text += string.Format("Key = {0}, Value = {1}", kvp.Key, kvp.Value); }
【解决方案2】:

您确实应该将 CSV 数据加载到数据表中,然后对其进行查询

var dt = SomeFunctionThatReadsCsvIntoDatatable(..);

yourDataGridView.DataSource = dt;

然后,您的查询将通过使用 linq 对数据表进行分组来简单地得到回答;

(yourDataGridView.DataSource as DataTable).Rows
    .Cast<DataRow>()
    .GroupBy(r => r["someColumn"])
    .Select(g => new { K = g.Key, C = g.Count() });
    
  • "someColumn" 将是 "SEX"
  • K 最终会成为 object 持有任何类型的数据 ` - 从发布的信息中很难判断您是否将 csv 作为字符串或它们是否是例如双打、日期等李>

如果您想对所有列执行此操作,那么在数据表 Columns 集合的循环中执行此操作可能是最简单的。 DataColumn.ColumnName 提供“someColumn”

【讨论】:

  • 是的,我正在使用 dt 来读取数据,我真的不认为我应该使用 linq。无论如何@JohnG 解决方案工作得很好。
猜你喜欢
  • 2021-12-04
  • 1970-01-01
  • 2011-03-31
  • 1970-01-01
  • 1970-01-01
  • 2020-11-13
  • 1970-01-01
  • 2017-09-14
  • 2021-07-28
相关资源
最近更新 更多