Создать сводную таблицу из таблицы данных - PullRequest
11 голосов
/ 02 апреля 2012

Я использую C # winforms, чтобы создать приложение, которое должно превратить данные в сводную таблицу.У меня есть сводная таблица работает нормально с конца SQL, но создание его из таблицы данных кажется сложнее.Я не мог найти что-то встроенное в .NET для этого.

ПРИМЕЧАНИЕ. Мне нужно сделать это со стороны .NET, поскольку я манипулирую данными до создания сводки.

Я прочитал несколько статей, которые делали подобные вещи, как эта, но мне было трудно применить их к моей проблеме.

* У меня есть таблица данных со столбцами «StartDateTime», «Tap» и «Data».Начальные даты должны быть сгруппированы, а значения данных усреднены (иногда более одного значения данных на начальную дату).Таблица показана ниже:

enter image description here

Сводная таблица должна выводиться так, как показано на рисунке ниже (хотя не округленные значения).Номера столбцов являются различными номерами ответвлений (по одному для каждого уникального).

Pivot Table

Как я могу создать эту сводную таблицу из таблицы данных?

РЕДАКТИРОВАТЬ: забыл упомянуть, эти значения не всегда 1-4, они различаются по количеству и значению.

Ответы [ 4 ]

4 голосов
/ 14 апреля 2015

Подобную сводную таблицу можно легко вычислить с помощью бесплатной NReco.PivotData библиотеки агрегации:

DataTable t;  // assume it has: StartDateTime, Data, Tap
var pivotData = new PivotData(
    new string[] {"StartDateTime","Tap"},
    new AverageAggregatorFactory("Data"),
    new DataTableReader(t) );
var pvtTbl = new PivotTable(
    new [] {"StartDateTime"},  // row dimension(s)
    new [] {"Tap"}, // column dimension(s),
    pivotData);

Ключи строк и столбцов представлены коллекциями pvtTbl.RowKeys и pvtTbl.ColumnKeys; значения / итоги могут быть доступны индексатором (например: pvtTbl[0,0].Value) или строкой + ключом столбца (например: pivotData[new Key(new DateTime(2012, 3, 30, 11, 42, 00)), new Key(4)].Value).

4 голосов
/ 02 апреля 2012

Изучите хэш-пивот tesuji:

var oDT = new DataTable;
var dfq = new Dictionary<DateTime, DataRow>;
oDT.Columns.Add("StartDateTime", typeof DateTime);
for (int i = 0; i < inDT.Rows.Count; i++) {
  var key = (DateTime)inDT.Rows[i][0];
  var row = (String)inDT.Rows[i][2];
  var data = (Double)inDT.Rows[i][1];
  if (!oDT.Columns.Contains(row))
      oDT.Columns.Add(row);
  if (dfq.ContainsKey(key)) {
      dfq[key][row] = data;
  } else {
      var oRow = oDT.NewRow();
      oRow[0] = key;
      oRow[row] = data;
      dfq.Add(key, oRow);
      oDT.Rows.Add(oRow);
  }
}
0 голосов
/ 12 сентября 2017

Еще один небольшой фрагмент кода для поворота любой таблицы, которую вы хотите:

        var dataTable = new DataTable(); // your input DataTable here!
        var pivotedDataTable = new DataTable(); //the pivoted result
        var firstColumnName = "Year";
        var pivotColumnName = "Codes";

        pivotedDataTable.Columns.Add(firstColumnName);

        pivotedDataTable.Columns.AddRange(
            dataTable.Rows.Cast<DataRow>().Select(x => new DataColumn(x[pivotColumnName].ToString())).ToArray());

        for (var index = 1; index < dataTable.Columns.Count; index++)
        {
            pivotedDataTable.Rows.Add(
                new List<object> { dataTable.Columns[index].ColumnName }.Concat(
                    dataTable.Rows.Cast<DataRow>().Select(x => x[dataTable.Columns[index].ColumnName])).ToArray());
        }
0 голосов
/ 09 января 2013

Может быть, это поможет вам.Это в vb.net.

Public Function pivot_datatable(ByVal datatable_source As DataTable, ByVal datacolumn_rows As DataColumn(), ByVal datacolumn_columns As DataColumn, ByVal datacolumn_value As DataColumn) As DataTable
    Dim temp_datacolumn As DataColumn
    Dim current_datarow As DataRow
    Dim datarow_destination As DataRow = Nothing
    Dim current_column_name As String = ""
    Dim primary_key() As DataColumn = New DataColumn() {}
    Dim key_columns() As Object
    Dim newOrdinal As Integer
    Dim i As Integer
    Dim sort_string As String = ""

    Try
        pivot_datatable = New DataTable()

        For Each temp_datacolumn In datatable_source.Columns
            If temp_datacolumn.Ordinal <> datacolumn_columns.Ordinal AndAlso temp_datacolumn.Ordinal <> datacolumn_value.Ordinal Then
                array_insert(primary_key, pivot_datatable.Columns.Add(temp_datacolumn.ColumnName, temp_datacolumn.DataType))
                sort_string &= temp_datacolumn.ColumnName & " ASC, "
            End If
        Next
        pivot_datatable.PrimaryKey = primary_key

        For Each current_datarow In datatable_source.Rows ' Main Process to add values to pivot table
            current_column_name = current_datarow(datacolumn_columns.Ordinal).ToString
            If Not pivot_datatable.Columns.Contains(current_column_name) Then ' Column is new
                temp_datacolumn = pivot_datatable.Columns.Add(current_column_name, datacolumn_value.DataType)
                newOrdinal = temp_datacolumn.Ordinal
                For i = newOrdinal - 1 To datatable_source.Columns.Count - 2 Step -1
                    If temp_datacolumn.ColumnName.CompareTo(pivot_datatable.Columns(i).ColumnName) < 0 Then
                        newOrdinal = i
                    End If
                Next
                temp_datacolumn.SetOrdinal(newOrdinal)
            End If

            key_columns = New Object() {}
            For Each data_column As DataColumn In datacolumn_rows
                array_insert(key_columns, current_datarow(data_column.Ordinal).ToString)
            Next data_column
            datarow_destination = pivot_datatable.Rows.Find(key_columns)
            If datarow_destination Is Nothing Then ' New Row
                datarow_destination = pivot_datatable.NewRow()
                For Each temp_datacolumn In datatable_source.Columns
                    If temp_datacolumn.Ordinal <> datacolumn_columns.Ordinal AndAlso temp_datacolumn.Ordinal <> datacolumn_value.Ordinal Then
                        datarow_destination(temp_datacolumn.ColumnName) = current_datarow(temp_datacolumn.ColumnName)
                    End If
                Next
                pivot_datatable.Rows.Add(datarow_destination)
            End If
            datarow_destination(current_column_name) = current_datarow(datacolumn_value.Ordinal)
        Next

        Return sort_datatable(pivot_datatable, sort_string.Substring(0, sort_string.Length - 2))
    Catch ex As Exception
        Return Nothing
    End Try
End Function
...