将DataTable列转换为类型IEnumerable []

时间:2016-11-29 23:03:28

标签: c# datatable casting ienumerable r.net

如何将DataTable列转换为在R.NET中创建数据框所需的IEnumerable []

我有以下代码:

DataTable dt = CreateDateTable();
REngine e = REngine.GetInstance();                       
IEnumerable[] columns = new IEnumerable[dt.Columns.Count];                
string[] columnNames = dt.Columns.Cast<DataColumn>()
                       .Select(x => x.ColumnName)
                       .ToArray();

for(int i=0; i<dt.Columns.Count; i++)
    //This is the place where I am stuck. How to convert column to base type array instead of object array
    columns[i] = dt.Rows.Cast<DataRow>().Select(row => row[i]).ToArray();

DataFrame df = e.CreateDataFrame(columns: columns, 
 columnNames: columnNames, 
 stringsAsFactors: false);

我得到以下异常:

Test 'XXX.ReadResultsTest' failed: System.NotSupportedException : Cannot convert type System.Object[] to an R vector
       w RDotNet.REngineExtension.ToVector(REngine engine, IEnumerable values)
       w System.Array.ConvertAll[TInput,TOutput](TInput[] array, Converter`2 converter)
       w RDotNet.REngineExtension.CreateDataFrame(REngine engine, IEnumerable[] columns, String[] columnNames, String[] rowNames, Boolean checkRows, Boolean checkNames, Boolean stringsAsFactors)

DataTable包含不同类型的列,我不知道这些类型是什么,所以我不能在这个示例中使用double

for (int i = 0; i < dt.Columns.Count; i++)
        columns[i] = dt.Rows.Cast<DataRow>().Select(row => row.Field<double>(i)).ToArray();

更新

到目前为止,我有一个丑陋的解决方案,可以做得更好吗?

for (int i = 0; i < dt.Columns.Count; i++)
{
    switch (Type.GetTypeCode(dt.Columns[i].DataType))
    {
        case TypeCode.String:
            columns[i] = dt.Rows.Cast<DataRow>().Select(row => row.Field<string>(i)).ToArray();
            break;

        case TypeCode.Double:
            columns[i] = dt.Rows.Cast<DataRow>().Select(row => row.Field<double>(i)).ToArray();
            break;

        case TypeCode.Int32:
            columns[i] = dt.Rows.Cast<DataRow>().Select(row => row.Field<int>(i)).ToArray();
            break;

        case TypeCode.Int64:
            columns[i] = dt.Rows.Cast<DataRow>().Select(row => row.Field<long>(i)).ToArray();
            break;

        default:
            //columns[i] = dt.Rows.Cast<DataRow>().Select(row => row[i]).ToArray();
            throw new InvalidOperationException(String.Format("Type {0} is not supported", dt.Columns[i].DataType.Name));
    }                
}

3 个答案:

答案 0 :(得分:1)

public DataFrame DataTableToDataFrame(string name, DataTable dt)
{
    DataFrame dataFrame = null;

    IEnumerable[] columns = new IEnumerable[dt.Columns.Count];
    string[] columnNames = dt.Columns.Cast<DataColumn>()
                           .Select(x => x.ColumnName)
                           .ToArray();

    for (int i = 0; i < dt.Columns.Count; i++)
    {
        switch (Type.GetTypeCode(dt.Columns[i].DataType))
        {
            case TypeCode.String:
                columns[i] = dt.Rows.Cast<DataRow>().Select(row => row.Field<string>(i)).ToArray();
                break;

            case TypeCode.Double:
                columns[i] = dt.Rows.Cast<DataRow>().Select(row => row.Field<double>(i)).ToArray();
                break;

            case TypeCode.Int32:
                columns[i] = dt.Rows.Cast<DataRow>().Select(row => row.Field<int>(i)).ToArray();
                break;

            case TypeCode.Int64:
            case TypeCode.Decimal:
                IEnumerable array = dt.Rows.Cast<DataRow>().Select(row => row.Field<object>(i)).ToArray();

                //columns[i] = dt.Rows.Cast<DataRow>().Select(row => row.Field<long>(i)).ToArray();
                //columns[i] = dt.Rows.Cast<DataRow>().Select(row => row.Field<decimal>(i)).ToArray();

                columns[i] = ListToIenumerable(array);
                break;

            default:
                columns[i] = dt.Rows.Cast<DataRow>().Select(row => row[i]).ToArray();
                //throw new InvalidOperationException(String.Format("Type {0} is not supported", dt.Columns[i].DataType.Name));
                break;
        }
    }

    dataFrame = REngine.CreateDataFrame(columns: columns, columnNames: columnNames, stringsAsFactors: false);
    REngine.SetSymbol(name, dataFrame);

    return dataFrame;
}

这是?

答案 1 :(得分:0)

以下是如何使用动态类型和扩展方法将DataTable对象转换为表示表列结构的对象的List(实现IEnumerable):

class Program
{
    static void Main()
    {
        var dt = new DataTable();
        //populate dt...

        List<dynamic> dataTableList= dt.DataTableToList();
    }
}

public static class DataTableExtensions
{
    public static List<dynamic> DataTableToList(this DataTable dt)
    {
        var list= new List<dynamic>();
        foreach (DataRow row in dt.Rows)
        {
            dynamic d = new ExpandoObject();
            list.Add(d);
            foreach (DataColumn column in dt.Columns)
            {
                var dic = (IDictionary<string, object>)d;
                dic[column.ColumnName] = row[column];
            }
        }

        return list;
    }
}

答案 2 :(得分:0)

public IEnumerable<int> ListToIenumerable(IEnumerable enumerable)
{
    List<int> list = new List<int>();

    foreach (object obj in enumerable)
    {
        list.Add(Convert.ToInt32(obj.ToString()));
    }

    IEnumerable<int> returnValue = list.ToArray();

    return returnValue;
}