Python 基于groupby将csv文件拆分数千次

Python 基于groupby将csv文件拆分数千次,python,csv,awk,Python,Csv,Awk,(大卫·埃里克森问题的改编) 给定包含列a、B和C以及一些值的CSV文件: echo 'a,b,c' > file.csv head -c 10000000 /dev/urandom | od -d | awk 'BEGIN{OFS = ","}{print $2, $3, $4}' | head -n 10000 >> file.csv 我们希望按a列和b列进行排序: sort -t ',' -k1,1n -k2,2n file.csv > file_.csv hea

(大卫·埃里克森问题的改编)

给定包含列a、B和C以及一些值的CSV文件:

echo 'a,b,c' > file.csv
head -c 10000000 /dev/urandom | od -d | awk 'BEGIN{OFS = ","}{print $2, $3, $4}' | head -n 10000 >> file.csv
我们希望按a列和b列进行排序:

sort -t ',' -k1,1n -k2,2n file.csv > file_.csv
head -n 3 file_.csv
>a,b,c
3,50240,18792
7,54871,39438
然后为每个唯一的对
(a,b)
创建一个名为
{a}\u Invoice{b}.CSV'
的新CSV

主要的挑战似乎是编写数千个文件的I/O开销——我开始尝试使用
awk
,但遇到
awk:17生成太多打开的文件

有没有一种更快的方法,用awk、Python或其他脚本语言来实现这一点

其他信息:

  • 我知道我可以在熊猫身上做到这一点——我正在寻找一种使用文本处理的更快方法
  • 虽然我使用了
    uradom
    来生成示例数据,但实际数据有重复出现的值:例如
    a=3,b=7的几行。如果是这样,则应将其保存为一个文件。(想法是复制熊猫的groupby->to_csv)
在python中:

将熊猫作为pd导入
df=pd.read\u csv(“file.csv”)
对于(a,b),df.groupby(['a','b'])中的gb:
gb.to_csv(f“{a}{u Invoice_{b}.csv”,header=True,index=False)

在awk中,您可以这样分割,您需要将头放回每个结果文件:

awk-F',“{out=$1”u Invoice_u“$2.csv”;print>>out;close(out)}”file.csv
通过向后添加标题行:

awk-F',''NR==1{hdr=$0;next}{out=$1”{u发票{u$2.csv;'if(!seen[out]++){print hdr>out}print>>out;close(out);}'file.csv
最后一个示例的好处是,输入
文件.csv
不需要排序,只需一次处理即可。

在python中:

将熊猫作为pd导入
df=pd.read\u csv(“file.csv”)
对于(a,b),df.groupby(['a','b'])中的gb:
gb.to_csv(f“{a}{u Invoice_{b}.csv”,header=True,index=False)

在awk中,您可以这样分割,您需要将头放回每个结果文件:

awk-F',“{out=$1”u Invoice_u“$2.csv”;print>>out;close(out)}”file.csv
通过向后添加标题行:

awk-F',''NR==1{hdr=$0;next}{out=$1”{u发票{u$2.csv;'if(!seen[out]++){print hdr>out}print>>out;close(out);}'file.csv

最后一个示例的好处是,输入
文件.csv
不需要排序,只需一次处理即可。

因为您的输入要按关键字段排序,所以您只需要:

sort -t ',' -k1,1n -k2,2n file.csv |
awk -F ',' '
NR==1 { hdr=$0; next }
{ out = $1 "_Invoice_" $2 ".csv" }
out != prev {
    close(prev)
    print hdr > out
    prev = out
}
{ print > out }
'

由于您的输入将按关键字段排序,因此您只需:

sort -t ',' -k1,1n -k2,2n file.csv |
awk -F ',' '
NR==1 { hdr=$0; next }
{ out = $1 "_Invoice_" $2 ".csv" }
out != prev {
    close(prev)
    print hdr > out
    prev = out
}
{ print > out }
'


您可以尝试用pandas加载原始文件,按(a,b)排序并从那里存储。看见您的问题是非主题的,并且使用多种语言。如果您只关心前两列,为什么不在排序和
.csv
文件创建之前删除第3列?并且@rtx13此示例中C列的数据仍然相关。它不会是基于A列和B列的动态文件名的一部分。从最初的链接问题中,我发现我在python中的方法生成.csv文件的速度有点慢,我想知道python中是否有更快的方法。Josh Friedlander认为这可能是awk会很快做到的事情。你可以尝试用pandas加载原始文件,按(a,b)排序并从那里存储。看见您的问题是非主题的,并且使用多种语言。如果您只关心前两列,为什么不在排序和
.csv
文件创建之前删除第3列?并且@rtx13此示例中C列的数据仍然相关。它不会是基于A列和B列的动态文件名的一部分。从最初的链接问题中,我发现我在python中的方法生成.csv文件的速度有点慢,我想知道python中是否有更快的方法。Josh Friedlander认为awk可能会很快做到这一点。是的,Python是原始问题中的方法。对于awk,它看起来很好——但是如果有多个相同的值,它会工作吗?例如,在a和b相同的几个连续行中,所需的输出是包含这些行的单个文件。是的,awk将附加到现有文件。您可以通过复制示例输入来测试这一点。您不需要单独的shell循环,只需将标题行打印到输出文件,一个简单的
!在awk脚本中看到[out]+{print hdr>out}
就可以了。您仍然需要更新现有脚本以跳过或以其他方式处理第一行,例如,
NR==1{hdr=$0;next}
。是的,Python是原始问题中的方法。对于awk,它看起来很好——但是如果有多个相同的值,它会工作吗?例如,在a和b相同的几个连续行中,所需的输出是包含这些行的单个文件。是的,awk将附加到现有文件。您可以通过复制示例输入来测试这一点。您不需要单独的shell循环,只需将标题行打印到输出文件,一个简单的
!在awk脚本中看到[out]+{print hdr>out}
就可以了。您仍然需要更新现有脚本以跳过或以其他方式处理第一行,例如,
NR==1{hdr=$0;next}
。这非常有效,谢谢!您是否希望它比Python中的等效程序更快?不客气。是的,但没有那么健壮,因为它没有Python做那么多的工作来验证CSV格式,因此,如果您的第一个字段可以被引用并包含逗号,例如,那么我希望使用CSV读取器的Python脚本能够正确处理该问题,而我发布的awk脚本则不能。请参阅如何使用awk稳健地处理CSV。@EdMorton,您好,Ed先生,很抱歉打扰您,只是尝试根据您在此处的指导生成数组名称。如果您有时间,请随时查看,先生。这非常有效,谢谢!你会期待它吗