如何将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));
}
}
答案 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;
}