0

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

文件1:

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
4

3 回答 3

2

一种灵活且通用的数据处理方式是 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

运行蟒蛇。. .

  • 使用 pandas read_csv 在 pandas 表结构中的文件中啜饮。(read_csv 非常聪明,可以读取多种格式,而不仅仅是 csv)
  • 使用 pandas 合并进行内部(索引的交集)连接,使用日期+时间作为索引(索引列表 = [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 A bog-standard(plain, unadorned) 'read_csv("File1")'将第一行视为标题名称。所以我们使用'header=None'。

>>> 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 'describe()'提供了有用的摘要,尤其是对于大表。对于数字数据,您还可以获得总计、最大值、最小值、平均值等

>>> 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 连接术语。how='left'将第一个文件索引(日期+时间)作为输出并合并到第二个文件数据中。how='right'将第二个文件索引作为输出并合并到第一个文件数据中。how='inner'在每个文件索引(日期+时间)之间进行交集,因此只有您在两个文件中都有条目的数据才会被获取。how='outer'在每个文件索引(日期+时间)之间进行联合,因此写入所有数据,在两个文件中都没有条目的数据填充有 'NaN' 值。

on/left_on/right_on index select我们也可以使用'on=[0,1]'因为我们的输入文件具有相同的索引列(并且它们被命名为与我们在文件中读取的相同的 0 和 1 与 'header=没有任何')。

>>> 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我们用'index=False'和'header=False'写出没有索引或标题。查看写入“Out2”文件的索引和标题的输出:

>>> 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
于 2015-10-13T10:51:03.870 回答
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

如果日期和时间不完全相等,则需要进行一些清理,因为上面的代码完全适用于所有内容的文本表示。只需将其弹出到tidyUpTimestamp程序中...</p>

于 2013-10-07T13:36:53.960 回答
1

假设这些文件分别没有重复,date,time我会将cat它们放在一起,sort并且awk如果当前行与date,time前一行相同,则打印上一行并从当前行附加数据:

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
于 2013-10-07T14:07:54.690 回答