【问题标题】:joining 2 csv files加入 2 个 csv 文件
【发布时间】:2017-10-19 19:52:42
【问题描述】:

加入.awk

#!/bin/awk -f
BEGIN {
    FS=OFS=",";
    print "ozone,particullate_matter,carbon_monoxide,sulfure_dioxide,nitrogen_dioxide,longitude,latitude,timestamp,avgMeasuredTime,avgSpeed,medianMeasuredTime,Distance between 2 points,duration of measurements,ndt in kmh"
}
NR==FNR && NR>1 {
    a[$8]=$1 FS $2 FS $3 FS $4 FS $5 FS $6 FS $7
}
FNR>1 {
if ($6 in a) {
    split(a[$6],data,FS);
    if ((data[6]==$11 || data[6]==$13) && (data[7]==$10 || data[7]==$12)) {
         print data[1],data[2],data[3],data[4],data[5],data[6],data[7],$6,$2,$3,$5,$14,$15,$16
        }
    }
}

我有这段代码,它合并了两个具有 3 个公共列的 csv 文件。我在 stackoverflow 的帮助下得到了这段代码。

输入文件1

ozone,particullate_matter,carbon_monoxide,sulfure_dioxide,nitrogen_dioxide,lon    gitude,latitude,timestamp
101,94,49,44,87,10.1050,56.2317,1406831700
106,97,48,47,86,10.1050,56.2317,1406832000
107,95,49,42,85,10.1050,56.2317,1406832300
103,90,51,44,87,10.1050,56.2317,1406832600

输入文件2

status,avgMeasuredTime,avgSpeed,extID,medianMeasuredTime,TIMESTAMP,vehicleCount,_id,REPORT_ID,Lat1,Long1,Lat2,Long2,Distance between 2 points,duration of measurements,ndt in kmh
OK,74,50,668,74,1406831700,5,20746220,158324,56.2317,10.1050,56.2258,10.1166,1030,52,71
OK,73,50,668,73,1406859900,6,20746392,158324,56.2317,10.1050,56.2258,10.1166,1030,52,71
OK,61,60,668,61,1406832300,4,20746723,158324,56.2317,10.1050,56.2258,10.1166,1030,52,71
OK,61,60,668,61,1406860500,1,20747172,158324,56.2317,10.1050,56.2258,10.1166,1030,52,71

输出

ozone,particullate_matter,carbon_monoxide,sulfure_dioxide,nitrogen_dioxide,longitude,latitude,timestamp,avgMeasuredTime,avgSpeed,medianMeasuredTime,Distance between 2 points,duration of measurements,ndt in kmh
101,94,49,44,87,10.1050,56.2317,1406831700,74,50,74,1030,52,71
107,95,49,42,85,10.1050,56.2317,1406832300,61,60,61,1030,52,71

每个输入文件有 1300000+ 行。

当我运行这个命令时 awk -f join.awk Inputfile1.csv Inputfile2.csv

我只打印了标题。但是此代码适用于较小的文件。 请帮忙

【问题讨论】:

  • 命令完成了吗?
  • awk -f join.awk ip1.csv ip2.csv ozone,particullate_matter,carbon_monoxide,sulfure_dioxide,nitrogen_dioxide,longitude,latitude,timestamp,avgMeasuredTime,avgSpeed,medianMeasuredTime,Distance between 2 points,duration of measurements,ndt in kmh 在此之后停止
  • 它是完成还是挂起?
  • 是的,先生,它完成了
  • 我的老眼睛欺骗了我。不是 10 美元。

标签: python bash csv join awk


【解决方案1】:

你可以使用join合并两个文件,然后打印出你想要的列:

join -j 1 -t ',' <( awk '{printf "%d,%s\n", NR, $0}' < test_file1 ) <( awk '{printf "%d,%s\n", NR, $0}' < test_file2 ) | awk -F ',' ' {print $2 FS $3}'

让我们分解一下:

首先,我们在每一行前面加上一个行号和一个逗号:

awk '{printf "%d,%s\n", NR, $0}' < test_file1

我们使用 bash 重定向将输出发送到 join 命令中。

# Join on field 1 (-j 1) using a seperator comma ( -t , )
join -j 1 -t ',' file_1 file_2

最后,我们通过管道将其传递给 awk 以打印出我们的字段:

awk -F ',' ' {print $2 FS $3 FS $8}'

【讨论】:

  • 先生,我想基于 3 列加入,即基于时间戳,file1 的经度,将其与 file2 的 2 个经度值进行比较,纬度类似。 @coder_man
  • 您可以比较 awk 语句中的字段。因此,您可以执行 if 语句然后打印,而不是打印。您可能希望执行 join 命令,然后打印出第一行并确定要执行的列。
【解决方案2】:

好吧,如果代码有效并且文件正常,那么假设散列到 a 的数据文件太大是合乎逻辑的。您可以拆分 Inputfile1 并使用 Inputfile2 分别运行每个部分,例如:

$ awk -f  join.awk Inputfile1_piece1.csv Inputfile2.csv
$ awk -f  join.awk Inputfile1_piece2.csv Inputfile2.csv
$ awk -f  join.awk Inputfile1_piece3.csv Inputfile2.csv
$ awk -f  join.awk Inputfile1_piece_etc.csv Inputfile2.csv

根据您的数据,尤其是$8,您可能需要处理重复项; a[$8]=$1 FS $2... 删除带有重复时间戳的行,其中随机拆分可能导致重复。在拆分之前排序会减少更改,但不会完全删除它,因此请检查每个文件的第一个和最后一个时间戳是否匹配。

但是:

我确实编写了以下 awk 脚本(更多是为了满足自己的好奇心),但您可以尝试将其用于您的数据。它假定文件按时间戳排序。它根本没有经过实战测试,只有您提供的小样本数据,它似乎清除了重复的记录,但不确定这是好是坏。

它从 2 个文件中读取记录,并且不会将它们散列到内存中。当来自其他文件的时间戳小于来自其他文件的时间戳时,继续浪费行(因此必须对时间戳进行排序)。

BEGIN {FS=OFS="," }
NR==1 {                             # read, form and print header
    if(0>=getline line < file1)     
        exit
    print line,$2,$3,$5,$(NF-1),$NF
    next                            # and deal (off) with the first records
}
$6>=a[8] {
    while((getline line < file1) > 0 && (n=split(line,a)) && a[8] < $6)
        ;
    if(a[8]==$6 && (a[6]==$11 || a[6]==$13) && (a[7]==$10 || a[7]==$12) && n>0)
        print line,$2,$3,$5,$(NF-1),$NF
}

运行它(Inputfile1 已经按时间戳排序,因此使用 getline 读取。Inputfile2 不是这样,它在进程替换中排序。记住对您的数据文件进行排序):

$ awk -v file1="Inputfile1" -f foo.awk <(sort -t, -k6n Inputfile2)
ozone,particullate_matter,carbon_monoxide,sulfure_dioxide,nitrogen_dioxide,longitude,latitude,timestamp,avgMeasuredTime,avgSpeed,medianMeasuredTime,duration of measurements,ndt in kmh
101,94,49,44,87,10.1050,56.2317,1406831700,74,50,74,52,71
107,95,49,42,85,10.1050,56.2317,1406832300,61,60,61,52,71

可能存在一百万个错误,使用风险自负,如果这样做,请验证、验证、验证结果。它只写入标准输出,所以它不应该破坏任何东西:D。 (所有人)如果您发现一些不合逻辑的地方,请随时修复它。

【讨论】:

  • awk -v file1="pollutionfile.csv" -f newjoin.awk
  • 文件是按时间戳字段排序的吗?这些数据在任何地方都可用吗?
  • 我已经根据时间戳字段对两个文件进行了排序
  • 请给我指向确切文件的链接,因为似乎有很多变化。
  • 先生,我对文件做了很多修改。我给你发邮件好吗?
猜你喜欢
  • 2017-10-19
  • 1970-01-01
  • 1970-01-01
  • 2012-07-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-07-09
相关资源
最近更新 更多