【问题标题】:Sorting of data of created text file对创建的文本文件的数据进行排序
【发布时间】:2020-01-05 11:04:12
【问题描述】:

我已将命令的输出转储到一个文本文件中,该文件包含多列结果多行。 第一列包含设备 ID,第二列包含时间(UTC)

我想根据增加的时间顺序(设置时间)对行进行排序。该怎么做?

这是我的命令输出(转储到文本文件):

Equipment ID  | Setup Time - GPS (UTC)                      | End Time - GPS (UTC)
            3 | 2068512564500 (2019-08-30 22:22:26.500 UTC) | 2068513054300 (2019-08-30 22:30:36.300 UTC)
            2 | 2068506579500 (2019-08-30 20:42:41.500 UTC) | 2068507041300 (2019-08-30 20:50:23.300 UTC)
            2 | 2068513133500 (2019-08-30 22:31:55.500 UTC) | 2068513614300 (2019-08-30 22:39:56.300 UTC)
            3 | 2068506038500 (2019-08-30 20:33:40.500 UTC) | 2068506399300 (2019-08-30 20:39:41.300 UTC)
            1 | 2068512827500 (2019-08-30 22:26:49.500 UTC) | 2068512852300 (2019-08-30 22:27:14.300 UTC)

【问题讨论】:

  • 将文本从文件读取到内存,将文本拆分为行(split("\n")),将每一行拆分为单元格(split("|")),使用第二列对所有数据进行排序(sort()sorted() ),将其写回文件。
  • 您可以使用模块pandas 并使用read_csv()| 作为分隔符将其读取到DataFrame。然后你可以在DataFrame 中排序并用to_csv() 写回
  • 在您的场景中,如何将输出通过管道传输到 .csv 文件?使用“|” char 作为其分隔符并使用 pythons csv 模块读取文件。
  • 在 Bash 中的 Linux 上,您可以执行 cat example.txt | sort -k 2,但它会将标头移到末尾。您必须使用headtail 将标题保持在顶部:Is there a way to ignore header lines in a UNIX sort?

标签: python python-2.7 sorting


【解决方案1】:

以下将从文件output.txt 加载数据并按SetupTime 的顺序打印出各个行:

import re

def collect_data(file_path):
    f = open(file_path, 'r')
    data = f.read()
    collection = []
    # RegExp with Capture Group around(0: The Whole Line, 1: Equipment ID, 2: SetupTime)
    data_rows = re.findall('((\d+) \| \d+ \((\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}.\d{3}) UTC\) \| \d+ \(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}.\d{3} UTC\))', data)
    for row in data_rows:
        collection.append(
            {
                'EquipmentId': row[1],
                'SetupTime': row[2],
                'Line': row[0]
            }
        )
    return collection

if __name__ == '__main__':
    collection = collect_data('output.txt')
    newlist = sorted(collection, key=lambda k: k['SetupTime'])
    for item in newlist:
        print(item['Line'])

输出:

3 | 2068506038500 (2019-08-30 20:33:40.500 UTC) | 2068506399300 (2019-08-30 20:39:41.300 UTC)
2 | 2068506579500 (2019-08-30 20:42:41.500 UTC) | 2068507041300 (2019-08-30 20:50:23.300 UTC)
3 | 2068512564500 (2019-08-30 22:22:26.500 UTC) | 2068513054300 (2019-08-30 22:30:36.300 UTC)
1 | 2068512827500 (2019-08-30 22:26:49.500 UTC) | 2068512852300 (2019-08-30 22:27:14.300 UTC)
2 | 2068513133500 (2019-08-30 22:31:55.500 UTC) | 2068513614300 (2019-08-30 22:39:56.300 UTC)

【讨论】:

    【解决方案2】:

    您可以使用模块pandas 中的DataFrame 并将其读取为带有分隔符| 的csv

    import pandas as pd
    
    df = pd.read_csv("data.txt", sep='|', dtype=str)
    df = df.sort_values(' Setup Time - GPS (UTC)                      ')
    df.to_csv('output.csv', sep='|', index=False)
    

    因为read_csv() 尝试将值转换为数字,所以我使用dtype=str 将所有值保留为字符串。

    我保留值和列名中的所有空格,以便稍后我可以像以前一样将其写回格式化。但我还必须在名称' Setup Time - GPS (UTC) ' 中使用空格来对其进行排序

    因为DataFrame 为每一行添加索引,所以我必须跳过to_csv() 中的索引


    编辑:示例使用io.StringIO 从内存而不是文件中读取数据,这样每个人都可以轻松地对其进行测试,而无需将数据保存在文件中。

    import pandas as pd
    import io
    
    data ='''Equipment ID  | Setup Time - GPS (UTC)                      | End Time - GPS (UTC)
                3 | 2068512564500 (2019-08-30 22:22:26.500 UTC) | 2068513054300 (2019-08-30 22:30:36.300 UTC)
                2 | 2068506579500 (2019-08-30 20:42:41.500 UTC) | 2068507041300 (2019-08-30 20:50:23.300 UTC)
                2 | 2068513133500 (2019-08-30 22:31:55.500 UTC) | 2068513614300 (2019-08-30 22:39:56.300 UTC)
                3 | 2068506038500 (2019-08-30 20:33:40.500 UTC) | 2068506399300 (2019-08-30 20:39:41.300 UTC)
                1 | 2068512827500 (2019-08-30 22:26:49.500 UTC) | 2068512852300 (2019-08-30 22:27:14.300 UTC)'''
    
    #file_ = "data.txt"
    file_ = io.StringIO(data)
    
    df = pd.read_csv(file_, sep='|', dtype=str)
    df = df.sort_values(' Setup Time - GPS (UTC)                      ')
    #df.to_csv('output.csv', sep='|', index=False)
    
    pd.options.display.width = 150
    pd.options.display.max_columns = 5
    print(df)
    

    结果为@​​987654332@:

       Equipment ID     Setup Time - GPS (UTC)                                                End Time - GPS (UTC)
    3              3    2068506038500 (2019-08-30 20:33:40.500 UTC)    2068506399300 (2019-08-30 20:39:41.300 UTC)
    1              2    2068506579500 (2019-08-30 20:42:41.500 UTC)    2068507041300 (2019-08-30 20:50:23.300 UTC)
    0              3    2068512564500 (2019-08-30 22:22:26.500 UTC)    2068513054300 (2019-08-30 22:30:36.300 UTC)
    4              1    2068512827500 (2019-08-30 22:26:49.500 UTC)    2068512852300 (2019-08-30 22:27:14.300 UTC)
    2              2    2068513133500 (2019-08-30 22:31:55.500 UTC)    2068513614300 (2019-08-30 22:39:56.300 UTC)
    

    【讨论】:

      【解决方案3】:

      如果您的文件不太长,我会简单地使用split()sorted(),仅此而已。

      txt = '''
      Equipment ID  | Setup Time - GPS (UTC)                      | End Time - GPS (UTC)
                  3 | 2068512564500 (2019-08-30 22:22:26.500 UTC) | 2068513054300 (2019-08-30 22:30:36.300 UTC)
                  2 | 2068506579500 (2019-08-30 20:42:41.500 UTC) | 2068507041300 (2019-08-30 20:50:23.300 UTC)
                  2 | 2068513133500 (2019-08-30 22:31:55.500 UTC) | 2068513614300 (2019-08-30 22:39:56.300 UTC)
                  3 | 2068506038500 (2019-08-30 20:33:40.500 UTC) | 2068506399300 (2019-08-30 20:39:41.300 UTC)
                  1 | 2068512827500 (2019-08-30 22:26:49.500 UTC) | 2068512852300 (2019-08-30 22:27:14.300 UTC)
      '''
      
      lines = []
      for line in txt.split('\n'):
          if len(line):
              lines.append(line.split('('))
      
      #Separate the header from the rest,
      #and sort the entries based on the Setup Time
      header, lines = lines[0], sorted(lines[1:], key=lambda x: x[1])
      
      #write back the sorted text
      sorted_txt = '('.join(header)
      for line in lines:
          sorted_txt += '\n' + '('.join(line)
      

      print(sorted_txt)的输出:

      Equipment ID  | Setup Time - GPS (UTC)                      | End Time - GPS (UTC)
                  3 | 2068506038500 (2019-08-30 20:33:40.500 UTC) | 2068506399300 (2019-08-30 20:39:41.300 UTC)
                  2 | 2068506579500 (2019-08-30 20:42:41.500 UTC) | 2068507041300 (2019-08-30 20:50:23.300 UTC)
                  3 | 2068512564500 (2019-08-30 22:22:26.500 UTC) | 2068513054300 (2019-08-30 22:30:36.300 UTC)
                  1 | 2068512827500 (2019-08-30 22:26:49.500 UTC) | 2068512852300 (2019-08-30 22:27:14.300 UTC)
                  2 | 2068513133500 (2019-08-30 22:31:55.500 UTC) | 2068513614300 (2019-08-30 22:39:56.300 UTC)
      

      当然,您可以将输出写入文件。

      如果您的文件很长,或者如果您需要在生产中一遍又一遍地重复此计算,那么请按照@furas 的建议选择 Pandas。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-10-15
        • 2016-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-10-28
        • 2018-05-08
        • 1970-01-01
        相关资源
        最近更新 更多