我正在尝试转置可能包含许多行和列的大型数据文件,以便在Excel中进行后续分析。目前行可能包含2或125,000个点,但我正在尝试通用。 (我需要进行转置,因为Excel无法处理那么多列,但如果大型集跨越多行,则可以正常。)
最初,我使用内置的zip函数实现了这个Python。我处理源文件以从short中分隔长行,然后用zip:
转置长行tempdata = zip(*csv.reader(open(tempdatafile,'r')))
csv.writer(open(outfile, 'a', newline='')).writerows(tempdata)
os.remove(tempdatafile)
对于15MB的csv文件来说效果很好并需要几秒钟,但由于首先生成数据的程序是在C#中,我认为最好在一个程序中完成所有操作。
我在C#中的初始方法有点不同,因为根据我的阅读,zip函数可能不会完全相同。这是我的方法:
public partial class Form1 : Form
{
StreamReader source;
int Rows = 0;
int Columns = 0;
string filePath = "input.csv";
string outpath = "output.csv";
List<string[]> test_csv = new List<string[]>();
public Form1()
{
InitializeComponent();
}
private void button_Load_Click(object sender, EventArgs e)
{
source = new StreamReader(filePath);
while(!source.EndOfStream)
{
string[] Line = source.ReadLine().Split(',');
test_csv.Add(Line);
if (test_csv[Rows].Length > Columns) Columns = test_csv[Rows].Length;
Rows++;
}
}
private void button_Write_Click(object sender, EventArgs e)
{
StreamWriter outfile = new StreamWriter(outpath);
for (int i = 0; i < Columns; i++)
{
string line = "";
for (int j = 0; j < Rows; j++)
{
try
{
if (j != 0) line += ",";
line += test_csv[j][i];
}
catch { }
}
outfile.WriteLine(line);
}
outfile.Close();
MessageBox.Show("Outfile written");
}
}
我使用List
因为行可能是可变长度的,并且我设置了load函数以给出总行数和行数,因此我可以知道outfile必须有多大。
我在编写处理可变长度行时使用了try/catch
。如果索引超出行的范围,则捕获异常并跳过它(下一个循环在发生异常之前写入逗号)。
加载只需要很少的时间,但实际上保存 outfile是一个非常漫长的过程。 2个小时后,我只通过文件的1/3。当我停止程序并查看outfile时,一切都正确完成了。
这个程序可能导致这么长时间的原因是什么?这都是异常处理吗?我可以实现第二个List
来存储每行的行长度,这样我就可以避免异常。这会解决这个问题吗?
答案 0 :(得分:3)
尝试使用StringBuilder
。连接(+
)长字符串的效率非常低。
创建List<string>
行,然后进行一次调用System.IO.File.WriteAllLines(filename, lines)
。这将减少磁盘IO。
如果您不关心积分的顺序,请尝试将您的外部循环更改为System.Threading.Tasks.Parallel.For
。这将运行多个线程。由于这些并行运行,因此在写出时不会保留顺序。
关于您的异常处理:由于这是您可以提前确定的错误,因此您不应使用try/catch
来处理它。将其更改为:
if (j < test_csv.Length && i < test_csv[j].Length)
{
line += test_csv[j][i];
}