我有多个文本文件(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 宏?
答案1
我能想到的最快的方法是使用 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"
}
- 将代码粘贴到新的文本文件中并将其另存为例如
MySplitMacro.ps1
- 编辑第一行并更改
$fullpath
为所需的 CSV 路径 - 右键单击该
.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 比较
使用的资源
答案2
您所要求的通常称为“控制中断”过程。有一个“控制”值。在您的情况下,它是物种。当它改变值或“中断”时,我们想要做某事。在您的情况下,您想要写出一个新文件。
有很多方法可以解决您的问题。我通常会使用脚本语言而不是 Excel 来解决它。
如果您有兴趣了解如何编写这样的程序/脚本,此链接将为您提供指导: http://www.unix.com/tips-and-tutorials/209439-how-do-control-break-algorithm.html
如果您使用的是 Windows 平台并且不介意使用编程语言,则可以使用 LinqPad (http://www.linqpad.net/) 有一个免费版本和以下 C# 程序(请确保在 LinqPad 语言下拉菜单中选择“C# 程序”):
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());
}
答案3
一个简单的 csv 搜索应用程序(如 CsvFileSearch)就可以做到这一点,而无需复杂化。它将搜索多个文件并将结果保存到另一个文件中。