6

У меня есть несколько текстовых файлов (CSV) со структурой, подобной этой:

funkiana,23.55,-99.866
funkiana,24.634,-98.701
funkiana,24.717,-98.901
geminiflora,22.25,-104.6166667
geminiflora,21.21666667,-104.65
horrida,19.633,-97.367
horrida,23.61666667,-102.575
horrida,22.158,-100.979
horrida,19.506,-97.433
horrida,17,-97.56667
horrida,19.485,-97.263
horrida,19.017,-99.133
horrida,19.017,-99.15
horrida,18.91,-99.23
horrida,17.82167,-100.26333
horrida,19.507,-97.438
inaequidens,19.399,-99.314
inaequidens,23.58333,-105.8833
inaequidens,19.767,-103.7
inaequidens,20.787,-103.848

Как видите, есть три поля (вид, широта и долгота). Теперь я хочу разбить каждый CSV-файл на разные CSV-файлы, содержащие только данные каждого вида. Другими словами, я хочу файл для всех случаев funkiana (с широтой / долготой), другой для geminiflora (с широтой / долготой) и так далее.

Есть идеи, как это сделать? Может быть, с помощью скрипта или макроса Excel?

3 ответа3

7

Самый быстрый способ, который я мог придумать, - это использовать PowerShell.

$fullpath = "D:\myFolder\input.csv"

$path = Split-Path $fullpath -parent
$data = Import-CSV -Delimiter "," -Path $fullpath -Header species,latitude,longitude  

foreach ($group in $data | Group species){        
    $data | Where-Object {$_.species -eq $group.name} | 
        ConvertTo-Csv -NoTypeInformation | 
        foreach {$_.Replace('"','')} | 
        Out-File "$path\$($group.name).csv"     
}
  1. Вставьте код в новый текстовый файл и сохраните его, например, как MySplitMacro.ps1
  2. Отредактируйте первую строку и измените $fullpath на желаемый путь CSV
  3. Щелкните правой кнопкой мыши файл .ps1 и выберите « Выполнить с помощью PowerShell».

Принимая ваш первоначальный пример в качестве входных данных, скрипт создаст 4 новых файла CSV в том же месте, что и ваш входной файл. Каждый CSV будет содержать один набор записей при фильтрации по первому столбцу.

Результирующий пример папки

Один полученный файл примера

Tweaks

  • Изменение вида в $data | Group species чтобы установить столбец для фильтрации
  • Измените -Delimiter "," если ваш входной файл имеет другой разделитель, такой как вкладки "` t "или точки с запятой"; "
  • Измените -Header species,latitude,longitude на имена столбцов. Заказать это правильно
  • Измените $path\$($group.name).csv если вам нужен другой выходной путь
  • Вместо -eq $group.name для фильтрации ваших результатов вы также можете использовать -like *$group.name* для сравнения с подстановочными знаками или -match '[A-Z]$group.name' для сравнения с RegEx.

Использованные ресурсы

0

Простое приложение для поиска в csv, такое как CsvFileSearch, сделает это без необходимости усложняться.Он будет искать несколько файлов и сохранить результаты в другой файл.

0

То, что вы просите, обычно называют процессом "перерыва в управлении". Есть "контрольное" значение. В вашем случае это вид. Когда это меняет значения или "ломает", мы хотим что-то сделать. В вашем случае вы хотите выписать новый файл.

Есть множество способов решить вашу проблему. Я обычно использовал бы язык сценариев против Excel, чтобы решить это.

Эта ссылка содержит подробное описание, если вам интересно узнать, как написать такую программу / скрипт: http://www.unix.com/tips-and-tutorials/209439-how-do-control-break-algorithm. HTML

Если вы работаете на платформе Windows и не возражаете против использования языка программирования, вы можете использовать LinqPad (http://www.linqpad.net/), который имеет бесплатную версию и следующую программу на C # (обязательно выберите " Программа C # "в раскрывающемся списке языков LinqPad):

void Main()
{
    var path = @"c:\sourceGit\speciesLatLon.txt";
    var inputLines = File.ReadAllLines(path);

    // Holds all the lines to be added to each output file
    var linesForCurrentSpeciesFile = new List<string>(); 

    // Read first row
    int i = 0;
    var currentSpecies = GetSpecies(inputLines[i]);

    // initialize hold value
    var holdValue = currentSpecies;

    // Initialize output values
    linesForCurrentSpeciesFile.Add(inputLines[i]);

    // Read next value
    i++;

    while( i < inputLines.Length )
    {
        currentSpecies = GetSpecies(inputLines[i]);
        if (currentSpecies !=  holdValue)
        {
            // output current file
            WriteSpeciesFile(holdValue, linesForCurrentSpeciesFile);

            // Initialize new output file by clearing out the previous
            linesForCurrentSpeciesFile.Clear();

            // update hold value with the value just examined.
            holdValue = currentSpecies;
        }
        // Add the current line to the output file
        linesForCurrentSpeciesFile.Add(inputLines[i]);
        i++;
    }
    // Write the output file because last row is equal to a break in the sequence
    WriteSpeciesFile(currentSpecies, linesForCurrentSpeciesFile);
}

// Define other methods and classes here
public string GetSpecies(string line)
{
    // return the first value of the input line
    return line.Split(new char[] {','})[0];
}

public void WriteSpeciesFile(string species, List<string> content)
{
    File.WriteAllLines(string.Format(@"C:\sourceGit\{0}.csv", species), content.ToArray());
}

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .