我有一个使用C#/ RDotNet的演示程序,该程序允许用户导入CSV,在网格上查看数据并提交R代码(就像您在R中一样)。
此程序是一个“概念验证”,用于查看是否可以将RDotNet合并到旧版程序中以替换其统计例程。
出于测试目的,我能够使用R读取CSV来创建数据框。这非常容易。使用RDotNet评估R代码:
MyFunctions._engine.Evaluate("dataset<-read.csv(file.choose(), sep = ',', stringsAsFactors = FALSE)");
DataFrame df = MyFunctions._engine.Evaluate("dataset").AsDataFrame();
我能够读取CSV,将数据添加到网格中,然后只需键入数据框的名称(“数据集”)就可以“看到”结果,就像您在R中一样。这是“ R_Test4.csv”的结果。
但是,我们的旧版软件将数据存储为DataTable。因此,当前的任务是将DataTable转换为R Dataframe。
我可以使用以下程序在某种程度上完成此任务: Link to GitHub program
我无法使用R读取数据。我必须模拟遗留程序的工作。因此,我使用流阅读器来读取CSV。问题是,在读取数据并将其加载到DataTable并将其转换为数据框后,在此过程中的某个位置,引号会添加到输出中。
我知道RDotNet具有“ CreateDataFrame”的方法,但是我无法弄清楚。因此,我知道还有另一种从数据表创建数据的方法,但是,我已经超越了我的能力编码。
我想要做的是使通过任何一种方法创建的数据框都相同。这是因为我希望本机R和.net方法的输出看起来完全相同。
任何人都可以提供有关确保数据表转换中没有引号或从数据表创建数据框的更好方法的建议吗?
以下是读取CSV并创建数据表的代码,然后使用.net方法(流读取器)将其转换为数据框。
private void btnChooseFileNet_Click(object sender, EventArgs e)
{
try
{
string strFileNameNet = "";
dataGridView1.DataSource = null;
dataGridView1.Rows.Clear();
dataGridView1.Columns.Clear();
dataGridView1.Refresh();
OpenFileDialog dialogNet = new OpenFileDialog() ;
dialogNet.Title = "Open CSV file";
dialogNet.Filter = "CSV Files (*.csv)|*.csv";
if (dialogNet.ShowDialog() == DialogResult.OK)
{
//btnChooseFileR.Enabled = false;
strFileNameNet = dialogNet.FileName;
using (StreamReader sr = new StreamReader(strFileNameNet))
{
DataTable netData = new DataTable();
string[] headers = sr.ReadLine().Split(',');
for (int i = 0; i < headers.Count(); i++)
{
netData.Columns.Add(headers[i], typeof(string));
}
while (!sr.EndOfStream)
{
string[] rows = sr.ReadLine().Split(',');
DataRow dr = netData.NewRow();
for (int i = 0; i < rows.Count(); i++)
{
dr[i] = rows[i];
}
netData.Rows.Add(dr);
}
dataGridView1.DataSource = netData;
ConvertDataTable(netData);
}
}
else
{
return;
}
}
catch (Exception ex)
{
Console.WriteLine("Error loading data using .Net: " + ex.Message);
}
}
public static DataFrame ConvertDataTable(DataTable dt)
{
//DataFrame df = null;
DataFrame df = MyFunctions._engine.Evaluate("df=NULL").AsDataFrame();
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.Decimal:
// IEnumerable array = dt.Rows.Cast<DataRow>().Select(row => row.Field<object>(i)).ToArray();
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));
//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] = dt.Rows.Cast<DataRow>().Select(row => row[i]).ToArray();
//columns[i] = ListToIenumerable(array);
break;
}
}
df = MyFunctions._engine.CreateDataFrame(columns: columns, columnNames: columnNames, stringsAsFactors: false);
MyFunctions._engine.SetSymbol("dataset", df);
return df;
}
}