Câu hỏi Làm cách nào để tách tệp CSV thành nhiều tệp dựa trên chuỗi văn bản?


Tôi có nhiều tệp văn bản (CSV) có cấu trúc tương tự như sau:

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

Như bạn có thể thấy, có ba trường (loài, vĩ độ và kinh độ). Bây giờ, tôi muốn chia từng tệp CSV thành các tệp CSV khác nhau, chỉ chứa dữ liệu của từng loài. Nói cách khác, tôi muốn một tập tin cho tất cả các lần xuất hiện của funkiana (với lat / lon), một cho geminiflora (với lat / lon) và vân vân.

Có ý tưởng nào để làm việc này không? Có thể với một kịch bản hoặc một macro Excel?


6
2017-08-01 01:03


gốc




Các câu trả lời:


Phương pháp nhanh nhất tôi có thể nghĩ đến là sử dụng 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. Dán mã vào một tệp văn bản mới và lưu nó thành ví dụ: MySplitMacro.ps1
  2. Chỉnh sửa dòng đầu tiên và thay đổi $fullpath vào đường dẫn CSV mong muốn của bạn
  3. Nhấp chuột phải vào .ps1 tệp và nhấp Chạy với PowerShell

Lấy ví dụ ban đầu của bạn làm đầu vào, tập lệnh sẽ tạo 4 tệp CSV mới tại cùng một vị trí với tệp nhập của bạn. Mỗi CSV sẽ chứa một tập hợp các mục nhập khi được lọc theo cột đầu tiên.

Thư mục ví dụ kết quả
enter image description here

Một tệp ví dụ kết quả
enter image description here

Tinh chỉnh

  • Thay đổi loài trong $data | Group species để đặt cột để lọc
  • Thay đổi -Delimiter "," nếu tệp nhập của bạn có dấu phân cách khác nhau như tab "` t "hoặc dấu chấm phẩy"; "
  • Thay đổi -Header species,latitude,longitude vào tên cột của bạn. Đặt hàng đúng cách
  • Thay đổi $path\$($group.name).csv nếu bạn cần một đường dẫn đầu ra khác
  • Thay vì -eq $group.name để lọc kết quả của bạn, bạn cũng có thể sử dụng -like *$group.name* để so sánh ký tự đại diện hoặc -match '[A-Z]$group.name' cho So sánh RegEx

Tài nguyên đã sử dụng


7
2017-08-01 04:49



Câu trả lời đẹp ... xin lỗi tôi chỉ có thể upvote nó chỉ một lần. - Gary's Student
Cảm ơn nhiều! Đây chính là điều tôi muốn làm :). Tôi sẽ kiểm tra các tài nguyên bạn đã sử dụng. Chắc chắn, tôi cần học kịch bản Power Shell. Cám ơn bạn một lần nữa. - Kureno


Những gì bạn đang yêu cầu thường được gọi là quá trình "kiểm soát ngắt". Có một giá trị "kiểm soát". Trong trường hợp của bạn, đó là loài. Khi điều này thay đổi giá trị hoặc "phá vỡ", chúng tôi muốn làm điều gì đó. Trong trường hợp của bạn, bạn muốn viết ra một tập tin mới.

Có rất nhiều cách để giải quyết vấn đề của bạn. Tôi thường sử dụng một ngôn ngữ kịch bản so với Excel để giải quyết nó.

Liên kết này đi qua nếu bạn quan tâm đến việc học cách viết một chương trình / tập lệnh như vậy: http://www.unix.com/tips-and-tutorials/209439-how-do-control-break-algorithm.html

Nếu bạn đang sử dụng nền tảng Windows và không ngại sử dụng ngôn ngữ lập trình, bạn có thể sử dụng LinqPad (http://www.linqpad.net/) có phiên bản miễn phí và chương trình C # sau (hãy nhớ chọn "Chương trình C #" trong trình đơn thả xuống Ngôn ngữ 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());
}

0
2017-08-01 03:21



Cảm ơn bạn vì câu trả lời. Tôi có rất ít kinh nghiệm với lập trình (đó là một điều mà tôi muốn giải quyết càng sớm càng tốt), nhưng chắc chắn tôi sẽ kiểm tra gợi ý của bạn. Ngoài ra, cảm ơn bạn đã đề cập đến tên của quá trình. Tôi đã nghi ngờ về tiêu đề của câu hỏi bởi vì tôi không biết làm thế nào để xác định nó: P. - Kureno


Một ứng dụng tìm kiếm csv đơn giản như CsvFileSearch sẽ làm điều này mà không cần phải phức tạp. Nó sẽ tìm kiếm nhiều tệp và lưu kết quả vào một tệp khác.


0
2017-08-27 18:42



Nhưng nó cũng có thể chia ra một tệp thành nhiều tệp? - Arjan
Thêm chi tiết vào câu trả lời của bạn - Prasanna