Pivot Methods 行列转换

本文介绍了一种使用 C# 实现数据透视表的方法,包括简单的轴翻转及基于三轴构建的新表两种方式,并提供了具体示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

The Pivot Methods

First - Simple Inversion

Read all data, and return all columns as lines and lines as columns.

The X axis column provided is used as the column header, and some columns may be ignored in the process, if desired so.

/// <summary>
/// Gets a Inverted DataTable
/// </summary>
/// <param name="table">DataTable do invert</param>
/// <param name="columnX">X Axis Column</param>
/// <param name="nullValue">null Value to Complete the Pivot Table</param>
/// <param name="columnsToIgnore">Columns that should be ignored in the pivot 
/// process (X Axis column is ignored by default)</param>
/// <returns>C# Pivot Table Method  - Felipe Sabino</returns>
public static DataTable GetInversedDataTable(DataTable table, string columnX, 
                                             params string[] columnsToIgnore)
{
    //Create a DataTable to Return
    DataTable returnTable = new DataTable();

    if (columnX == "")
        columnX = table.Columns[0].ColumnName;

    //Add a Column at the beginning of the table

    returnTable.Columns.Add(columnX);

    //Read all DISTINCT values from columnX Column in the provided DataTale
    List<string> columnXValues = new List<string>();

    //Creates list of columns to ignore
    List<string> listColumnsToIgnore = new List<string>();
    if (columnsToIgnore.Length > 0)
        listColumnsToIgnore.AddRange(columnsToIgnore);

    if (!listColumnsToIgnore.Contains(columnX))
        listColumnsToIgnore.Add(columnX);

    foreach (DataRow dr in table.Rows)
    {
        string columnXTemp = dr[columnX].ToString();
        //Verify if the value was already listed
        if (!columnXValues.Contains(columnXTemp))
        {
            //if the value id different from others provided, add to the list of 
            //values and creates a new Column with its value.
            columnXValues.Add(columnXTemp);
            returnTable.Columns.Add(columnXTemp);
        }
        else
        {
            //Throw exception for a repeated value
            throw new Exception("The inversion used must have " + 
                                "unique values for column " + columnX);
        }
    }

    //Add a line for each column of the DataTable

    foreach (DataColumn dc in table.Columns)
    {
        if (!columnXValues.Contains(dc.ColumnName) && 
            !listColumnsToIgnore.Contains(dc.ColumnName))
        {
            DataRow dr = returnTable.NewRow();
            dr[0] = dc.ColumnName;
            returnTable.Rows.Add(dr);
        }
    }

    //Complete the datatable with the values
    for (int i = 0; i < returnTable.Rows.Count; i++)
    {
        for (int j = 1; j < returnTable.Columns.Count; j++)
        {
            returnTable.Rows[i][j] = 
              table.Rows[j - 1][returnTable.Rows[i][0].ToString()].ToString();
        }
    }

    return returnTable;
}
Second - Pivoting

It uses the idea of three axes to build the new table. The X axis column is the column with the Unique Values to build the columns header. The Y axis value is the column with the values to be displayed as the rows in the first column. The Z axis is the "value" and is the match of X and Y in the DataSource, and can be the sum of values if more than one different value is found in the process. The null value is provided in case there is the need to fill empty cells of the table with a certain value.

The flag to sum values is used in case there is more than one value for a certain X and Y column combination; if it is "false", the last value that is read is displayed.

/// <summary>
/// Gets a Inverted DataTable
/// </summary>
/// <param name="table">Provided DataTable</param>
/// <param name="columnX">X Axis Column</param>
/// <param name="columnY">Y Axis Column</param>
/// <param name="columnZ">Z Axis Column (values)</param>
/// <param name="columnsToIgnore">Whether to ignore some column, it must be 
/// provided here</param>
/// <param name="nullValue">null Values to be filled</param> 
/// <returns>C# Pivot Table Method  - Felipe Sabino</returns>
public static DataTable GetInversedDataTable(DataTable table, string columnX, 
     string columnY, string columnZ, string nullValue, bool sumValues)
{
    //Create a DataTable to Return
    DataTable returnTable = new DataTable();

    if (columnX == "")
        columnX = table.Columns[0].ColumnName;

    //Add a Column at the beginning of the table
    returnTable.Columns.Add(columnY);


    //Read all DISTINCT values from columnX Column in the provided DataTale
    List<string> columnXValues = new List<string>();

    foreach (DataRow dr in table.Rows)
    {

        string columnXTemp = dr[columnX].ToString();
        if (!columnXValues.Contains(columnXTemp))
        {
            //Read each row value, if it's different from others provided, add to 
            //the list of values and creates a new Column with its value.
            columnXValues.Add(columnXTemp);
            returnTable.Columns.Add(columnXTemp);
        }
    }

    //Verify if Y and Z Axis columns re provided
    if (columnY != "" && columnZ != "")
    {
        //Read DISTINCT Values for Y Axis Column
        List<string> columnYValues = new List<string>();

        foreach (DataRow dr in table.Rows)
        {
            if (!columnYValues.Contains(dr[columnY].ToString()))
                columnYValues.Add(dr[columnY].ToString());
        }

        //Loop all Column Y Distinct Value
        foreach (string columnYValue in columnYValues)
        {
            //Creates a new Row
            DataRow drReturn = returnTable.NewRow();
            drReturn[0] = columnYValue;
            //foreach column Y value, The rows are selected distincted
            DataRow[] rows = table.Select(columnY + "='" + columnYValue + "'");

            //Read each row to fill the DataTable
            foreach (DataRow dr in rows)
            {
                string rowColumnTitle = dr[columnX].ToString();

                //Read each column to fill the DataTable
                foreach (DataColumn dc in returnTable.Columns)
                {
                    if (dc.ColumnName == rowColumnTitle)
                    {
                        //If Sum of Values is True it try to perform a Sum
                        //If sum is not possible due to value types, the value 
                        // displayed is the last one read
                        if (sumValues)
                        {
                            try
                            {
                                drReturn[rowColumnTitle] = 
                                     Convert.ToDecimal(drReturn[rowColumnTitle]) + 
                                     Convert.ToDecimal(dr[columnZ]);
                            }
                            catch
                            {
                                drReturn[rowColumnTitle] = dr[columnZ];
                            }
                        }
                        else
                        {
                            drReturn[rowColumnTitle] = dr[columnZ];
                        }
                    }
                }
            }
            returnTable.Rows.Add(drReturn);
        }
    }
    else
    {
        throw new Exception("The columns to perform inversion are not provided");
    }

    //if a nullValue is provided, fill the datable with it
    if (nullValue != "")
    {
        foreach (DataRow dr in returnTable.Rows)
        {
            foreach (DataColumn dc in returnTable.Columns)
            {
                if (dr[dc.ColumnName].ToString() == "")
                    dr[dc.ColumnName] = nullValue;
            }
        }
    }

    return returnTable;
}

Using the Code

The article provides two ways to perform a Pivot transformation.

In both ways, the table below will be used as an example of the data source:

EmployeeIDOrderIDAmountCostDate
Sam1251301/10/2007
Sam2512102/10/2007
Sam3512103/10/2007
Tom450104/10/2007
Tom53703/10/2007
Tom678,751202/10/2007
Sue711701/10/2007
Sue82,566,202/10/2007
Sue92,52203/10/2007
Jack1062302/10/2007
Jack1111719904/10/2007
Jack12132,601/10/2007
Jack1311,499,803/10/2007
Phill14372,102/10/2007
Phill1565,299,304/10/2007
Phill1634,12702/10/2007
Phill171795904/10/2007

The code below shows how to create the table above:

DataTable dt = new DataTable();

dt.Columns.Add("EmployeeID", Type.GetType("System.String"));
dt.Columns.Add("OrderID", Type.GetType("System.Int32"));
dt.Columns.Add("Amount", Type.GetType("System.Decimal"));
dt.Columns.Add("Cost", Type.GetType("System.Decimal"));
dt.Columns.Add("Date", Type.GetType("System.String"));
dt.Rows.Add(new object[] { "Sam", 1, 25.00, 13.00, "01/10/2007" });
dt.Rows.Add(new object[] { "Sam", 2, 512.00, 1.00, "02/10/2007" });
dt.Rows.Add(new object[] { "Sam", 3, 512.00, 1.00, "03/10/2007" });
dt.Rows.Add(new object[] { "Tom", 4, 50.00, 1.00, "04/10/2007" });
dt.Rows.Add(new object[] { "Tom", 5, 3.00, 7.00, "03/10/2007" });
dt.Rows.Add(new object[] { "Tom", 6, 78.75, 12.00, "02/10/2007" });
dt.Rows.Add(new object[] { "Sue", 7, 11.00, 7.00, "01/10/2007" });
dt.Rows.Add(new object[] { "Sue", 8, 2.50, 66.20, "02/10/2007" });
dt.Rows.Add(new object[] { "Sue", 9, 2.50, 22.00, "03/10/2007" });
dt.Rows.Add(new object[] { "Jack", 10, 6.00, 23.00, "02/10/2007" });
dt.Rows.Add(new object[] { "Jack", 11, 117.00, 199.00, "04/10/2007" });
dt.Rows.Add(new object[] { "Jack", 12, 13.00, 2.60, "01/10/2007" });
dt.Rows.Add(new object[] { "Jack", 13, 11.40, 99.80, "03/10/2007" });
dt.Rows.Add(new object[] { "Phill", 14, 37.00, 2.10, "02/10/2007" });
dt.Rows.Add(new object[] { "Phill", 15, 65.20, 99.30, "04/10/2007" });
dt.Rows.Add(new object[] { "Phill", 16, 34.10, 27.00, "02/10/2007" });
dt.Rows.Add(new object[] { "Phill", 17, 17.00, 959.00, "04/10/2007" });
First - Simple Inversion

A column is provided and the DataTable has its "axes turned". This method makes it possible to ignore some columns during the inversion, so that the return table has only the columns of interest. If we want to invert with the column "OrderID" as the title (X axis column), we should use the code below:

//For example, for the DataTable  provided as Datasource 
DataTable dtReturn = GetInversedDataTable(dt, "OrderID");

The return table will be like the one below:

Second - Pivot Table

The three columns are provided and a new DataTable is returned.

The example below will use the source table and the params below to build a Pivot Table.

  • X axis column: "Date"
  • Y axis column: "EmployeeID"
  • Z axis column: "Cost"
  • Null value: "-";
  • Sum of values: true
//For example, for the DataTable  provided as Datasource 
DataTable dtReturn = GetInversedDataTable(dt, "Date", "EmployeeID", 
                                          "Cost", "-", true);

The return table will be like the one below:

EmployeeID01/12/200702/12/200703/12/200704/12/2007
Sam1311-
Tom-1271
Sue766,222-
Jack2,62399,8199
Phill-27-959

Points of Interest

转载于:https://www.cnblogs.com/happy-Chen/p/3623256.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值