加入2个csv文件

时间:2017-05-19 15:46:40

标签: python bash csv join awk

join.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中的人的帮助下得到了这段代码。

Inputfile1

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

Inputfile2

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

我只得到标题打印。但是这段代码适用于较小的文件。 请帮忙

2 个答案:

答案 0 :(得分:0)

您可以使用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}'

答案 1 :(得分:0)

好吧,如果代码有效并且文件很好,那么假设数据文件散列到<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>React, Babel, Webpack 2</title> </head> <body class="container"> <div id="app"></div> <script src="jquery.timeago.js"></script> <script src="client.min.js"></script> </body> </html>太大是合乎逻辑的。您可以拆分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 ...删除具有重复时间戳的行,其中随机拆分可能导致重复。在拆分之前进行排序会减少其更改但不会完全删除它,因此请检查每个文件的第一个和最后一个时间戳以进行匹配。

<强> BUT:

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

它从2个文件中读取记录,并且不会将它们哈希到内存中。虽然来自其他文件的时间戳小于另一个文件的时间戳,但要保持浪费行(因此必须订购时间戳)。

a[$8]=$1 FS $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

可能有一百五十个错误,使用风险自负,如果您这样做,请验证,验证,验证结果。它只写入stdout所以它不应该破坏任何东西:D。 (每个人)如果你看到一些不合逻辑的话,请随意修理它。