Python 按目标列值将CSV文件拆分为多个CSV
一般来说,我对编程和Python相当陌生。我有一个大的CSV文件,需要根据目标列(最后一列)的目标值将其拆分为多个CSV文件 这是我想要拆分的CSV文件数据的简化版本Python 按目标列值将CSV文件拆分为多个CSV,python,csv,Python,Csv,一般来说,我对编程和Python相当陌生。我有一个大的CSV文件,需要根据目标列(最后一列)的目标值将其拆分为多个CSV文件 这是我想要拆分的CSV文件数据的简化版本 1254.00 1364.00 4562.33 4595.32 1 1235.45 1765.22 4563.45 4862.54 1 6235.23 4563.00 7832.31 5320.36 1 8623.75 5632.09 4586.25 9361.86
1254.00 1364.00 4562.33 4595.32 1
1235.45 1765.22 4563.45 4862.54 1
6235.23 4563.00 7832.31 5320.36 1
8623.75 5632.09 4586.25 9361.86 0
5659.92 5278.21 8632.02 4567.92 0
4965.25 1983.78 4326.50 7901.10 1
7453.12 4993.20 4573.30 8632.08 1
8963.51 7496.56 4219.36 7456.46 1
9632.23 7591.63 8612.37 4591.00 1
7632.08 4563.85 4632.09 6321.27 0
4693.12 7621.93 5201.37 7693.48 0
6351.96 7216.35 795.52 4109.05 0
我希望分割,以便输出提取不同csv文件中的数据,如下所示:
sample1.csv
1254.00 1364.00 4562.33 4595.32 1
1235.45 1765.22 4563.45 4862.54 1
6235.23 4563.00 7832.31 5320.36 1
sample2.csv
8623.75 5632.09 4586.25 9361.86 0
5659.92 5278.21 8632.02 4567.92 0
sample3.csv
4965.25 1983.78 4326.50 7901.10 1
7453.12 4993.20 4573.30 8632.08 1
8963.51 7496.56 4219.36 7456.46 1
9632.23 7591.63 8612.37 4591.00 1
sample4.csv
7632.08 4563.85 4632.09 6321.27 0
4693.12 7621.93 5201.37 7693.48 0
6351.96 7216.35 795.52 4109.05 0
我尝试使用pandas和一些groupby函数,但它将所有1和0合并到单独的文件中,一个包含所有值的1和另一个0,这不是我需要的输出
任何帮助都将不胜感激。您所能做的就是获取每行最后一列的值。如果该值与前一行中的值相同,则将该行添加到同一列表中,如果不是,则创建一个新列表并将该行添加到该空列表中。对于数据结构,请使用列表列表。假设文件“input.csv”包含原始数据
1254.00 1364.00 4562.33 4595.32 1
1235.45 1765.22 4563.45 4862.54 1
6235.23 4563.00 7832.31 5320.36 1
8623.75 5632.09 4586.25 9361.86 0
5659.92 5278.21 8632.02 4567.92 0
4965.25 1983.78 4326.50 7901.10 1
7453.12 4993.20 4573.30 8632.08 1
8963.51 7496.56 4219.36 7456.46 1
9632.23 7591.63 8612.37 4591.00 1
7632.08 4563.85 4632.09 6321.27 0
4693.12 7621.93 5201.37 7693.48 0
6351.96 7216.35 795.52 4109.05 0
代码如下
target = None
counter = 0
with open('input.csv', 'r') as file_in:
lines = file_in.readlines()
tmp = []
for idx, line in enumerate(lines):
_target = line.split(' ')[-1].strip()
if idx == 0:
tmp.append(line)
target = _target
continue
else:
last_line = idx + 1 == len(lines)
if _target != target or last_line:
if last_line:
tmp.append(line)
counter += 1
with open('sample{}.csv'.format(counter), 'w') as file_out:
file_out.writelines(tmp)
tmp = [line]
else:
tmp.append(line)
target = _target
也许你想要这样的东西:
from itertools import groupby
from operator import itemgetter
sep = ' '
with open('data.csv') as f:
data = f.read()
split_data = [row.split(sep) for row in data.split('\n')]
gb = groupby(split_data, key=itemgetter(4))
for index, (key, group) in enumerate(gb):
with open('sample{}.csv'.format(index), 'w') as f:
write_data = '\n'.join(sep.join(cell) for cell in group)
f.write(write_data)
与
pd.groupby
不同,itertools.groupby
不会事先对源代码进行排序。这会将输入CSV解析为列表列表,并基于包含目标的第5列对外部列表执行groupby。groupby对象是组的迭代器;通过将每个组写入不同的文件,可以获得您想要的结果。我建议使用一个函数来完成要求的操作
有可能保留未引用的
我们已经为写作而打开,因此当
垃圾已收集,但这里我更喜欢显式关闭每个输出
在打开另一个文件之前,请先保存该文件
该脚本有大量注释,因此没有进一步解释:
def split_data(data_fname, key_len=1, basename='file%03d.txt')
data = open(data_fname)
current_output = None # because we have yet not opened an output file
prev_key = int(1) # because a string is always different from an int
count = 0 # because we want to count the output files
for line in data:
# line has a trailing newline so that to extract the key
# we have to take into account that
key = line[-key_len-1:-1]
if key != prev_key # key has changed!
count += 1 # a new file is going to be opened
prev_key = key # remember the new key
if current_output: # if a file was opened, close it
current_output.close()
# open a new output file, its name derived from the variable count
current_output = open(basename%count, 'w')
# now we can write to the output file
current_output.write(line)
# note that line is already newline terminated
# clean up what is still going
current_output.close()
这个答案是正确的。您尝试过什么?只要在文件上迭代,每次当最后一列中的值发生变化时,就开始写入新文件……您的输出与我的错误输出类似。我不希望我的输出仅在两个文件中—一个包含0,另一个包含1。你可以检查我在问题中给出的期望输出。还是谢谢你!您已要求根据最后一列“target”创建输出文件。这就是代码的作用。。请解释当您提供的数据源中只有两个目标[0,1]时,代码应该如何创建sample3.csv等文件。感谢您的努力。我想要的迭代是,在数据中,我们看到前3行的目标值为1。因此,sample1.csv文件应该包含前3行。当目标值从1更改为0时,它应该创建一个新的sample2.csv,其中下两行包含目标值0。然后,当迭代器发现目标值从0更改为1(在第6行中)时,它应该创建一个新的sample3.csv,并使用目标值1放置下一行,以此类推。我希望澄清。请看一看我原来的问题。在这里,我已经解释了我想要的输出。谢谢好啊知道了。代码被修改了。看一看,谢谢。我试过你的改良版。但我得到的是12个sample.csv文件,而不是4个csv文件。因为每一行现在都被创建为csv文件,而不是目标值组。您的输出:sample1.csv 1254.00 1364.00 4562.33 4595.32 1 sample2.csv 1235.45 1765.22 4563.45 4862.54 1我想要的地方:sample1.csv 1254.00 1364.00 4562.33 4595.32 1235.45 1765.22 4563.45 4862.54 16235.23 4563.00 7832.31 5320.36 1谢谢。但是我发现你的第10行有索引错误。索引器:列出索引,共个range@MishkatRahman问题可能是我给出的代码假设源文件的格式与问题中所述的完全相同(元素之间有3个空格)。如果它确实是您所述的CSV,则需要将
sep
值更改为其他值。好的。谢谢马库斯的帮助!谢谢你的解释。请问,在您的修改版本中,我应该如何处理f.write(line)?因为我们没有任何参考f。其中,在您以前的代码中,f=None。我在重构时忘记了名称转换。。。哎哟当然,它应该是当前的输出。写入(行),因为我们要在那里写入我们正在处理的行。我已经编辑了答案,我为错误和随之而来的混乱道歉。