将多个文件附加到一个文件中,跳过第一行并排序

append multiple files into one, skip the first row and sort

我有一个文件夹,其中包含每小时值的月度文件。 12 个文件中的每一个都有一行 header。每个文件都有一行代表那个月的每个站的每小时。见下文:

Hours   stn stn_id  sen_id  Elevation   Latitude    Longitude   cnt avg_hrly
2010-01-01 00:00:00 Alberni 108 217 26  49.24596024 -124.8041687    60  0.0
2010-01-01 01:00:00 Alberni 108 217 26  49.24596024 -124.8041687    59  0.0
...
2010-01-31 22:00:00 Alberni 108 217 26  49.24596024 -124.8041687    60  0.0
2010-01-31 23:00:00 Alberni 108 217 26  49.24596024 -124.8041687    60  0.0
...
2010-01-01 00:00:00 Arbutus 79  159 57  48.47133255 -123.30664062   60  0.0
2010-01-01 01:00:00 Arbutus 79  159 57  48.47133255 -123.30664062   60  0.0
...

问题是,到了 3 月,夏令时班次的每个文件中都有上个月的一个小时,如下所示:

Hours   stn stn_id  sen_id  Elevation   Latitude    Longitude   cnt avg_hrly
2010-05-31 23:00:00 Alberni 108 217 26  49.24596024 -124.8041687    60  0.0
2010-06-01 00:00:00 Alberni 108 217 26  49.24596024 -124.8041687    56  0.0
...

附加部分非常简单,但我确信有更好的方法,尤其是考虑到我还需要做两件事:

  1. 跳过每个附加文件的 header。没关系第一个实例,我可以在顶部粘贴一个。
  2. 根据第 2 列对生成的附加文件进行排序以获取站名,然后在第 1 列按小时对每个站进行排序。

期望的结果:

2010-01-01 00:00:00 Alberni 108 217 26  49.24596024 -124.8041687    60  0.0
2010-01-01 01:00:00 Alberni 108 217 26  49.24596024 -124.8041687    59  0.0
...
2010-01-31 22:00:00 Alberni 108 217 26  49.24596024 -124.8041687    60  0.0
2010-01-31 23:00:00 Alberni 108 217 26  49.24596024 -124.8041687    60  0.0
2010-02-01 00:00:00 Alberni 108 217 26  49.24596024 -124.8041687    60  0.0
2010-02-01 01:00:00 Alberni 108 217 26  49.24596024 -124.8041687    60  0.0
2010-02-01 02:00:00 Alberni 108 217 26  49.24596024 -124.8041687    60  0.0
...
2010-05-31 20:00:00 Alberni 108 217 26  49.24596024 -124.8041687    60  0.6
2010-05-31 21:00:00 Alberni 108 217 26  49.24596024 -124.8041687    60  0.0
2010-05-31 22:00:00 Alberni 108 217 26  49.24596024 -124.8041687    60  0.0
2010-05-31 23:00:00 Alberni 108 217 26  49.24596024 -124.8041687    60  0.0
2010-06-01 00:00:00 Alberni 108 217 26  49.24596024 -124.8041687    56  0.0
2010-06-01 01:00:00 Alberni 108 217 26  49.24596024 -124.8041687    60  0.0
2010-06-01 02:00:00 Alberni 108 217 26  49.24596024 -124.8041687    60  0.0
2010-06-01 03:00:00 Alberni 108 217 26  49.24596024 -124.8041687    60  0.0
2010-06-01 04:00:00 Alberni 108 217 26  49.24596024 -124.8041687    60  10.4

我想知道这是否需要一些 awk 和 shell 结合使用管道?

下面是一些伪伪代码,简单传达一下做法:

for file in *.csv; do awk NR>1 {print} | sort -k2,1n | >> year_appended.csv ; done

也许这是一个使用 Python 更好地克服的挑战,也许使用 Pandas 库来处理时间序列。如果是这样,我猜是一组语句,或两个。

使用 GNU 排序 -s(稳定排序):

awk 'FNR > 1' *.csv | sort -sk 2,2 | sort -sk 3,3

此处 awk 'FNR > 1' 过滤不是文件第一行的行1sort -sk m,n 按字段稳定排序 m通过 n。要不仅按小时而且按日期排序,请使用

awk 'FNR > 1' *.csv | sort -sk 1,2 | sort -sk 3,3

请注意,这取决于日期和时间格式。幸运的是,日期和时间戳的字典顺序比较适用于给定的表示,因此不需要更复杂的解析。

1不需要明确的 { print } 操作;当条件为真时执行默认操作(打印)。

附录:如果你有 GNU awk 并且文件中的字段严格以制表符分隔,你也可以使用

gawk -F '\t' 'FNR > 1 { data[,] = [=12=] } END { PROCINFO["sorted_in"] = "@ind_str_asc"; for(d in data) print data[d] }' *.csv

此处-F '\t'告诉gawk将行沿制表符拆分为字段,代码工作如下:

FNR > 1 {                                  # for all lines that are not the
                                           # first of a file:
  data[,] = [=13=]                         # remember them by fields 2 and 1
}
END {
  PROCINFO["sorted_in"] = "@ind_str_asc"   # GNU-specific: Require sorted
                                           # traversal of arrays.

  for(d in data) {                         # Then print the lines in that
    print data[d]                          # sorted order.
  }
}

一些伪代码,你不需要跳过这里的行,因为 concatenation 会为你对齐列,而且只制作一个 dfs 列表然后连接它们会更快一起而不是一次附加一个 df:

# assuming you have a list of the files you want to load, probably via glob

df_list=[]
for file in file_list:
    df_list.apend(pd.read_csv(file, parse_dates=['Hours']))

merged = pd.concat(df_list)
# sort the data
merged = merged.sort(['stn', 'Hours'])