如果时间戳匹配,则解析两个文件并合并行

时间:2013-10-07 10:08:49

标签: bash sed awk tcl

我有两个以下格式的数据文件:

File1中:

date,time,data1,data2,data3
date,time,data1,data2,data3
date,time,data1,data2,data3

文件2:

date,time,data4
date,time,data4

我想要做的是合并这两个文件中的行,如果日期和时间匹配,那么输出应该是:

date,time,data1,data2,data3,data4

如果一个文件中的时间戳与另一个文件中的任何内容都不匹配,那么我可以忽略该行。

我目前正在使用awk和join的组合。但我想知道这是否是最有效的方法。

目前的工作实施是这样的:

 awk 'FS="," {print $1"&"$2 ","$3","$4","$5}' File1 > temp1
 awk 'FS="," {print $1"&"$2 ","$3}' File2 > temp2
 join -t',' -j1 1 -o 1.1,1.2,1.3,2.2,2.3 temp1 temp2 > temp3
 awk 'FS="&" {print $1","$2"}' temp3 > Output

3 个答案:

答案 0 :(得分:1)

我这样做的方式(假设日期和时间具有精确匹配格式)将是:

proc tidyUpTimestamp {date time} {
    # If you want to parse/tidy up the timestamp, do so here
    return $date,$time
}

# Schlurp the data into an array for ease of access. Good for a few million lines
set f [open "file2.csv"]
foreach line [split [read $f] "\n"] {
    lassign [split $line ","] date time data4
    set map([tidyUpTimestamp $date $time]) $data4
}
close $f

# Assuming that file1.csv is much longer than file2.csv
set fin [open "file1.csv"]
set fout [open "file1.processed.csv" w]
while {[gets $fin line] >= 0} {
    lassign [split $line ","] date time;   # Ignore other fields...
    set ts [tidyUpTimestamp $date $time]
    if {[info exist map($ts)]} {
        # Simple concatenation!
        puts $fout "$line,$map($ts)"
    }
}
close $fout
close $fin

如果日期和时间不完全相同,则需要进行一些清理,因为上述代码完全依赖于所有内容的 textual 表示。只需将其弹出到tidyUpTimestamp程序......

答案 1 :(得分:1)

假设这些文件没有重复date,time我会cat他们在一起,sortawk如果当前行具有相同的date,time { {1}}如前一个那样打印上一行并从当前行追加数据:

cat file1.txt file2.txt | \
    sort | \
    awk '
function getOnlyData()
{
    onlyData="";
    for (i=3;i<=NF;i++)
    {
        onlyData = onlyData "," $i;
    }
    return onlyData
}
BEGIN {
    FS=",";
}
{
    if (prevDate==$1 && prevTime==$2)
    {
        currData = getOnlyData()
        print $1 "," $2 prevData currData
    }
    prevDate=$1;
    prevTime=$2;
    prevData=getOnlyData();
}'

输入:

2013-10-07,12:00:00,a1,b1,c1
2013-10-07,13:00:00,a2,b2,c2
2013-10-07,14:00:00,a3,b3,c3
2013-10-07,15:00:00,x4,y4,z4
2013-10-07,16:00:00,x5,y5,z5

2000-10-07,12:00:00,d1
2013-10-07,13:00:00,d2
2000-10-07,14:00:00,d3
2013-10-07,15:00:00,d4
2000-10-07,16:00:00,d5

输出是:

2013-10-07,13:00:00,a2,b2,c2,d2
2013-10-07,15:00:00,d4,x4,y4,z4

答案 2 :(得分:1)

操作数据的灵活而通用的方法是python pandas。值得一提的是,它确实是适合这项工作的工具。允许在选定的索引行或列上进行电子表格或数据库样式合并/连接/连接。

两个示例文件来说明它是如何工作的

$ cat File1
date0,time0,data01,data02,data03
date1,time1,data11,data12,data13
date2,time2,data21,data22,data23
date3,time3,data31,data32,data33
date4,time4,data41,data42,data43
date5,time5,data51,data52,data53
$ cat File2
date1,time1,data14
date4,time4,data44
date2,time2,data24

运行python。 。

  • 使用pandas read_csv来覆盖pandas表结构中的文件。 (read_csv非常聪明,可以读取多种格式而不仅仅是csv)
  • 使用pandas merge做内部(指数交集)连接, 使用日期+时间作为索引(索引列表= [0,1])。
  • 使用pandas to_csv写入输出。

重要的比特:

$ python
>>> from pandas import merge, read_csv
>>> f1=read_csv("File1",header=None)
>>> f2=read_csv("File2",header=None)
>>> merged = merge(f1, f2, how='inner', left_on=[0,1], right_on=[0,1])
>>> merged.to_csv("Out", na_rep=0, index=False, header=False)
>>> [Ctrl-D]

完成工作!

$ cat Out
date1,time1,data11,data12,data13,data14
date2,time2,data21,data22,data23,data24
date4,time4,data41,data42,data43,data44

非常干净,没有弄乱。我真的很喜欢bash / grep / sed / awk perl和python在结构中操作数据但正确的工作工具使工作变得更加容易,并且更有可能使用数据。

<强>故障:

<强> 1。 read_csv 沼泽标准(简单,朴素)&#39; read_csv(&#34; File1&#34;)&#39; 将第一行视为标题名称。所以我们使用&#39; header = None&#39;。

>>> f1=read_csv("File1")
>>> f1
date0  time0  data01  data02  data03
0  date1  time1  data11  data12  data13
1  date2  time2  data21  data22  data23
2  date3  time3  data31  data32  data33
3  date4  time4  data41  data42  data43
4  date5  time5  data51  data52  data53
>>> f1=read_csv("File1",header=None)
>>> f1
0      1       2       3       4
0  date0  time0  data01  data02  data03
1  date1  time1  data11  data12  data13
2  date2  time2  data21  data22  data23
3  date3  time3  data31  data32  data33
4  date4  time4  data41  data42  data43
5  date5  time5  data51  data52  data53
>>> f2=read_csv("File2",header=None)

pandas DataFrame&#39; describe()&#39; 为大表提供了有用的摘要。对于数字数据,您还可以获得总数,最大值,最小值,平均值,e.t.c。

>>> f1.describe()
0      1       2       3       4
count       6      6       6       6       6
unique      6      6       6       6       6
top     date4  time3  data01  data12  data13
freq        1      1       1       1       1

<强> 2。合并

如何指定左/右/内/外合并样式sql join术语。 how =&#39; left&#39; 将第一个文件索引(日期+时间)作为输出并合并到第二个文件数据中。 how =&#39; right&#39; 将第二个文件索引作为输出并合并到第一个文件数据中。 how =&#39; inner&#39; 执行每个文件索引(日期+时间)之间的交集,因此只会获取两个文件中都有条目的数据。 how =&#39; outer&#39; 在每个文件索引(日期+时间)之间建立联合,以便写入所有数据,在两个文件中没有条目的数据都用&填充#39; NaN的&#39;值。

on / left_on / right_on index select 我们还可以使用&#39; on = [0,1]&#39; ,因为我们的输入文件具有相同的索引列(并且它们的名称与我们在文件中读取的0和1相同,其中&#39; header = None&#39;)。

>>> merged = merge(f1, f2, how='inner', left_on=[0,1], right_on=[0,1])
>>> merged
0      1     2_x       3       4     2_y
0  date1  time1  data11  data12  data13  data14
1  date2  time2  data21  data22  data23  data24
2  date4  time4  data41  data42  data43  data44
>>> mergedOut = merge(f1, f2, how='outer', left_on=[0,1], right_on=[0,1])
>>> mergedOut
0      1     2_x       3       4     2_y
0  date0  time0  data01  data02  data03     NaN
1  date1  time1  data11  data12  data13  data14
2  date2  time2  data21  data22  data23  data24
3  date3  time3  data31  data32  data33     NaN
4  date4  time4  data41  data42  data43  data44
5  date5  time5  data51  data52  data53     NaN

第3。 to_csv 我们使用&#39; index = False&#39;写出没有和索引或标题和&#39; header = False&#39;。查看输出的索引和标题写入&#34; Out2&#34;文件:

>>> merged.to_csv("Out2")
>>> merged.to_csv("Out", na_rep=0, index=False, header=False)

$ cat Out2
,0,1,2_x,3,4,2_y
0,date1,time1,data11,data12,data13,data14
1,date2,time2,data21,data22,data23,data24
2,date4,time4,data41,data42,data43,data44
$ cat Out
date1,time1,data11,data12,data13,data14
date2,time2,data21,data22,data23,data24
date4,time4,data41,data42,data43,data44

开始使用的文档:

获取pandas并安装:http://pandas.pydata.org/getpandas.html

# download, unpack and:
sudo python setup.py install