Использование C# System.Diagnostics для запуска R для обработки информации и передачи результатов обратно на консоль.C#

Место общения программистов C#
Ответить
Anonymous
 Использование C# System.Diagnostics для запуска R для обработки информации и передачи результатов обратно на консоль.

Сообщение Anonymous »

У меня есть устаревшее приложение C#, которое использует таблицы данных в своих операциях.
Мне нужно передать информацию из таблицы данных в программе C# в R; затем заставьте R обработать данные, используя инструкции из файла сценария, проделайте некоторую работу с переданными данными; затем верните результаты из R обратно в C#.
Чтобы объяснить, я написал короткое консольное приложение.
Я пробовал это так много раз разными способами, но результат всегда один и тот же:

Код: Выделить всё

System.IO.IOException: 'The pipe is being closed.'
Эта ошибка возникает на первой итерации. Я не уверен, что R открывается успешно, но если да, то закрывается немедленно.
РЕДАКТИРОВАТЬ: после просмотра документов MS и прочтения этой ссылки, кажется, что инициализация Rscript.exe не происходит даже до запуска StreamWriter (ошибка ввода-вывода выше). Это ошибка, которую я получаю в MainModule, когда устанавливаю точку останова после «process.start()»

Код: Выделить всё

'process.MainModule' threw an exception of type 'System.ComponentModel.Win32Exception'
Это странно, потому что изначально я использовал 64-битную версию R, а конфигурация моего решения была настроена для x64.
После прочтения этого исключения Я установил более низкую версию R (3.6.3) с 32-битной версией exe и попробовал ее. Независимо от того, та же ошибка.
Итак, я не уверен, почему Rscript.exe не запускается. Думаю, я перепробовал все возможные варианты (например, 32-битную, 64-битную).
-- КОНЕЦ РЕДАКТИРОВАНИЯ --Что касается аргументов, я перепробовал очень много комбинаций (вот только пара):
  • Arguments = "-c " + scriptPath ,
  • Аргументы = scriptPath,
  • Arguments = "-c -q --vanilla --file=" + scriptPath (EDIT: дополнение)
Я успешно использовал аналогичный код для отправки команд в Rscript.exe из программы C# и захвата вывода обратно на консоль. используя другую программу, но был использован первый аргумент выше.
Я также написал много разных сценариев R, но я не думаю, что они имели значение на данном этапе, поскольку процесс немедленно отключается.
Вот программа на C#:

Код: Выделить всё

using System;
using System.Data;
using System.Diagnostics;
using System.IO;
using System.Text;

public class RandomDataToR
{
public static void Main(string[] args)
{
// Create data
int row_cnt = 10;
double x_bar = 50;
double sd = 10;

// Generate random numbers with mean x_bar and StdDev sd
double[] data = GenerateRandomData(row_cnt, x_bar, sd);

// Create a DataTable
DataTable dt = CreateDataTable(data);

// Send data to R program
string rAppPath = @"C:\Program Files\R\R-4.3.0\bin\Rscript.exe";
string rScript = @"C:\Temp\ConsoleApp\get_output.r";
string results = SendDataToExe(dt, rAppPath, rScript);
Console.WriteLine(results);
}

private static double[] GenerateRandomData(int count, double mean, double stdDev)
{
double[] data = new double[count];
var random = new Random();
for (int i = 0; i < count; i++)
{

double u1 = 1.0 - random.NextDouble();
double u2 = 1.0 - random.NextDouble();
double rndStdNorm = Math.Sqrt(-2.0 * Math.Log(u1)) * Math.Sin(2.0 * Math.PI * u2);
data[i] = mean + stdDev * rndStdNorm;
}

return data;
}

private static DataTable CreateDataTable(double[] data)
{
DataTable dataTable = new DataTable();
dataTable.Columns.Add("Data", typeof(double));
foreach (double value in data)
{
dataTable.Rows.Add(Math.Round(value, 2));
}
return dataTable;
}

private static string SendDataToExe(DataTable dt, string exePath, string scriptPath)
{
string unixSyleScript = scriptPath.Replace("\\", "/");

// Serialize DataTable to a CSV format
StringBuilder csvData = new StringBuilder();
foreach (DataRow row in dt.Rows)
{
csvData.AppendLine(row["Data"].ToString());
}

// Setup the process start info
ProcessStartInfo startInfo = new ProcessStartInfo()
{
FileName = exePath,
Arguments = "--vanilla --file=" + unixSyleScript,
RedirectStandardInput = true,
RedirectStandardOutput = true,
UseShellExecute = false,
CreateNoWindow = true
};

// Execute Rscript and send the data
using (Process process = new Process { StartInfo = startInfo })
{
process.Start();

using (StreamWriter sw = process.StandardInput)
{
if (sw.BaseStream.CanWrite)
{
sw.Write(csvData.ToString());
sw.Flush();
}
}

// Read the output from the R script until "**DONE**" is received
string output;
string errors;
do
{
output = process.StandardOutput.ReadToEnd();
errors = process.StandardError.ReadToEnd();
} while (output != null && !output.Equals("**DONE**"));

if (process != null)
{
process.WaitForExit();  // Wait for the process to finish
}

if (!string.IsNullOrEmpty(errors))
{
Console.WriteLine("Errors from Rscript: " + errors);
}

return output;
}
}
}
Вот программа R "get_output.r":

Код: Выделить всё

# Read data from standard input
data 

Подробнее здесь: [url]https://stackoverflow.com/questions/78410126/using-c-sharp-system-diagnostics-to-launch-r-to-process-information-and-pass-res[/url]
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C#»