Як розділити файл CSV на кілька файлів на основі текстового рядка?


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(з lat / lon), інший для geminiflora(з lat / lon) тощо.

Будь-які ідеї, як це зробити? Можливо, зі сценарієм або макросом Excel?

Відповіді:


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 буде містити один набір записів, відфільтрований за першим стовпцем.

Отриманий приклад папки
введіть тут опис зображення

Один отриманий приклад-файл
введіть тут опис зображення

Налаштування

  • Зміна видів в $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

Використовувані ресурси


Прекрасна відповідь ... Вибачте, що я можу підтвердити це лише один раз.
Студент Гері

Велике спасибі! Це саме те, що я хотів зробити :). Я перевірю використані вами ресурси. Безумовно, мені потрібно вивчити сценарії Power Shell. Ще раз дякую вам.
Курено

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());
}

Спасибі за вашу відповідь. У мене дуже мало досвіду роботи з програмуванням (це одне, що я хочу вирішити якнайшвидше), але, безумовно, я перевірю вашу пропозицію. Також дякую за згадування назви процесу. У мене виникли сумніви щодо назви питання, оскільки я не знав, як його визначити: P.
Курено

0

Простий додаток пошуку CSV, такий як CsvFileSearch, зробить це без необхідності ускладнення. Він буде шукати кілька файлів і зберігати результати в інший файл.


Але чи може він також розділити файл на кілька файлів?
Ар'ян

Додайте більше деталей у свою відповідь
Прасанна
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.