Преобразование DataTable в Dataframe с использованием RDotNet
У меня есть демонстрационная программа, использующая C#/RDotNet, которая позволяет пользователю импортировать CSV, просматривать данные в сетке и отправлять R-код (как если бы вы были в R).
Эта программа является "доказательством концепции", чтобы посмотреть, сможем ли мы включить RDotNet в устаревшую программу, чтобы заменить ее статистические процедуры.
В целях тестирования я смог прочитать в CSV, используя R для создания кадра данных. Это работает очень легко. Использование 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.
Я смог сделать это в некоторой степени, используя программу здесь: Ссылка на программу GitHub
Я не мог использовать R для чтения в данных. Я должен был симулировать, что делает наша старая программа. Итак, я использовал потоковый ридер для чтения CSV. Проблема заключается в том, что после того, как вы прочитаете данные и загрузите их в DataTable и преобразуете в фрейм данных, где-то по пути к кавычкам добавляются выходные данные.
Я знаю, что в RDotNet есть метод "CreateDataFrame", но я не мог понять это. Итак, я знаю, что есть другой способ создания данных из таблицы данных, но я продвинулся далеко вперед от кодирования моих способностей.
То, что я пытаюсь сделать, - это иметь одинаковые кадры данных, созданные любым методом. Это потому, что я хочу, чтобы выходные данные native 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;
}
}