【问题标题】:How can I sort that table in Python on Linux [duplicate]如何在 Linux 上的 Python 中对该表进行排序 [重复]
【发布时间】:2013-06-14 23:16:22
【问题描述】:
import sys, subprocess, glob

mdbfiles = glob.glob('*.res')
for DATABASE in mdbfiles: 

    subprocess.call(["mdb-schema", DATABASE, "mysql"])

    table_names = subprocess.Popen(["mdb-tables", "-1", DATABASE],
                                   stdout=subprocess.PIPE).communicate()[0]
    tables = table_names.splitlines()

    sys.stdout.flush()

    a=str('Channel_Normal_Table')

    for table in tables:
        if table != '' and table==a:

            filename = DATABASE.replace(".res","") + ".csv"
            file = open(filename, 'w')
            print("Dumping " + table)
            contents = subprocess.Popen(["mdb-export", DATABASE, table],
                                        stdout=subprocess.PIPE).communicate()[0]

            # I NEED TO PUT SOMETHING HERE TO SORT AND EXTRACT THE DATA I NEED


            file.write(contents)
            file.close()

我有一个从数据库中提取的表。让我们称之为table。我需要执行以下操作,我有点卡住了:

Cycle Test_Time  Current    Voltage
1     7.80E-002 0.00E+000   1.21E-001
1     3.01E+001 0.00E+000   1.19E-001
1     6.02E+001 0.00E+000   1.17E-001
2     9.02E+001 0.00E+000   1.14E-001
2     1.20E+002 0.00E+000   1.11E-001
2     1.50E+002 0.00E+000   1.08E-001
2     1.80E+002 0.00E+000   1.05E-001
2     2.10E+002 0.00E+000   1.02E-001
3     2.40E+002 0.00E+000   9.93E-002
3     2.70E+002 0.00E+000   9.66E-002
3     3.00E+002 0.00E+000   9.38E-002
3     3.10E+002 4.00E-001   1.26E+000
  1. 提取每个周期的最后(最新)行,或者更高级地对周期进行排序 按时间提取循环中时间最晚的行。作为 你可以看到,最后一行并不总是有最新的时间,因为 我们的测试机故障,但通常会发生。但越大的 时间越晚。
  2. 提取最后五个周期的所有行
  3. 提取周期 4 到周期 30 的所有行。

我尝试了各种方法,例如根据我有限的 Python 知识创建和排序字典和列表,但都没有产生所需的输出。它只是让我发疯。非常感谢!

【问题讨论】:

  • 你可能想看看 Pandas:pandas.pydata.org
  • 这些是使用 awk 和其他 shell 实用程序非常简单的任务
  • 为什么不能在数据库本身中执行此操作?
  • 伙计们。这是我必须完成的项目。我们正在将脚本从 bash 转换为 Python。我有需要处理的 .mdb 文件。所以我能够提取必要的表格,但我需要对该表格进行排序并提取特定数据。我不是程序员,对 Python 知之甚少,因此将不胜感激。谢谢。

标签: python linux sorting csv dictionary


【解决方案1】:

这并不难,但你必须一步一步来:

from collections import defaultdict

table = """\
Cycle Test_Time  Current    Voltage
1     7.80E-002 0.00E+000   1.21E-001
1     3.01E+001 0.00E+000   1.19E-001
1     6.02E+001 0.00E+000   1.17E-001
2     9.02E+001 0.00E+000   1.14E-001
2     1.20E+002 0.00E+000   1.11E-001
2     1.50E+002 0.00E+000   1.08E-001
2     1.80E+002 0.00E+000   1.05E-001
2     2.10E+002 0.00E+000   1.02E-001
3     2.40E+002 0.00E+000   9.93E-002
3     2.70E+002 0.00E+000   9.66E-002
3     3.00E+002 0.00E+000   9.38E-002
3     3.10E+002 4.00E-001   1.26E+000"""

# Split into rows
table = table.splitlines()

# Split each row into values
table = [row.split() for row in table]

# Associate the column names with their index
headers = table.pop(0)
H = {x: i for i, x in enumerate(headers)}
time_index = H["Test_Time"]
cycle_index = H["Cycle"]

# Sort by Test_Time
table.sort(key=lambda row: float(row[time_index]))

# Associate each test with its cycle
D = defaultdict(list)
for row in table:
  D[int(row[cycle_index])].append(row)

# Present the information
print(*headers, sep='\t')
print("Latest row for each cycle")
for cycle in sorted(D.keys()):
  tests = D[cycle]
  latest_test = tests[-1]
  print(*latest_test, sep='\t')

print("All rows for last 5 cycles")
for cycle in sorted(D.keys())[-5:]:
  tests = D[cycle]
  for test in tests:
    print(*test, sep='\t')

print("All rows for cycles 4 through 30")
for cycle in sorted(D.keys()):
    if 4 <= cycle <= 30:
      tests = D[cycle]
      for test in tests:
        print(*test, sep='\t')

【讨论】:

  • 谢谢!我现在就试试。另一件事。如何将处理后的内容保存到 .csv 文件中?
  • 查看pythoncsv module
  • 我收到一个错误:'字母数字字符和下划线:%r' % name) ValueError:类型名称和字段名称只能包含字母数字字符和下划线:'Test_ID,Data_Point,Test_Time,Step_Time, DateTime,Step_Index,Cycle_Index,Is_FC_Data,Current,Voltage,Charge_Capacity,Discharge_Capacity,Charge_Energy,Discharge_Energy,dV/dt,Internal_Resistance,AC_Impedance,ACI_Phase_Angle'
  • 尝试将 namedtuple 行更改为 namedtuple("table_row", headers, rename=True)。您似乎使用了示例文件中的不同标头?如果这对您有用,请务必接受答案!
  • 再次感谢。是的,我使用了不同的标题,因为整个表格有 26 列长并且可以有数百万行。我添加了 True 语句,但现在出现另一个错误:table = [table_row(int(c), float(t), float(i), float(v)) for c, t, i, v in table[1 :]] ValueError: need more than 1 value to unpack >>> 当然我会接受答案。我只需要让那个脚本工作。一整天都在和它战斗,没有结果。我对 Python 有点陌生,到目前为止,所有这些东西对我来说都非常复杂((
【解决方案2】:

您可以使用pandaspymdb 轻松完成您的工作

使用 pandas,您可以轻松处理时间序列数据。 看看 pandas.DataFrame。这就是你所需要的。

【讨论】:

    【解决方案3】:

    首先,让我们读取文件并将找到的值转换为循环 col 的整数和浮点数:

    databyrow=[]
    with open('/tmp/temps.txt', 'r') as f:
        header=f.readline().strip().split()
        for line in f:
            temp=[]
            for i,val in enumerate(line.strip().split()):
                fn=int if i==0 else float
                try:
                    val=fn(val)
                except ValueError:
                    print val,'not converted'
                temp.append(val)    
            databyrow.append(temp)                
    print databyrow  
    

    打印:

     [[1, 0.078, 0.0, 0.121],
     [1, 30.1, 0.0, 0.119],
     [1, 60.2, 0.0, 0.117],
     [2, 90.2, 0.0, 0.114],
     [2, 120.0, 0.0, 0.111],
     [2, 150.0, 0.0, 0.108],
     [2, 180.0, 0.0, 0.105],
     [2, 210.0, 0.0, 0.102],
     [3, 240.0, 0.0, 0.0993],
     [3, 270.0, 0.0, 0.0966],
     [3, 300.0, 0.0, 0.0938],
     [3, 310.0, 0.4, 1.26]]
    

    现在您可以根据刚刚创建的列表列表中的循环 col 列表创建组字典:

    from itertools import groupby
    keyfn=lambda t:t[0]
    sorted_input=sorted(databyrow,key=keyfn)
    data_bycycle={k:list(g) for k,g in groupby(sorted_input,key=keyfn)}
    

    打印:

    {1: [[1, 0.078, 0.0, 0.121], [1, 30.1, 0.0, 0.119], [1, 60.2, 0.0, 0.117]], 
     2: [[2, 90.2, 0.0, 0.114], [2, 120.0, 0.0, 0.111], [2, 150.0, 0.0, 0.108], [2, 180.0, 0.0, 0.105], [2, 210.0, 0.0, 0.102]], 
     3: [[3, 240.0, 0.0, 0.0993], [3, 270.0, 0.0, 0.0966], [3, 300.0, 0.0, 0.0938], [3, 310.0, 0.4, 1.26]]}
    

    现在您可以直接获取每个循环的最后 N 行:

    >>> N=2
    >>> data_bycycle[1][-N:]
    [[1, 30.1, 0.0, 0.119], [1, 60.2, 0.0, 0.117]]    
    

    如果您希望该组中的一个按最新时间排序:

    >>> sorted(data_bycycle[2],key=lambda li: li[1])[-1]
    [2, 210.0, 0.0, 0.102]  
    

    编辑

    下载链接的保管箱文件,您有一个 csv 文件——不是空格分隔的。

    下面是这样的阅读方法:

    import csv
    
    databyrow=[]
    with open('/tmp/VC0307a.csv', 'r') as f:      # potentially you can use 'contents' here
        for i,row in enumerate(csv.reader(f)):
            if i==0:
                header=row
            else:
                temp=[]
                for j,val in enumerate(row):
                    fn=int if j in (0,1) else float
                    try:
                        val=fn(val)
                    except ValueError:
                        print val, 'not converted'
                    temp.append(val)     
                databyrow.append(temp)
    

    一旦你在内存中,你可以按某个数字列排序:

    >>> header
    ['Test_ID', 'Data_Point', 'Test_Time', 'Step_Time', 'DateTime', 'Step_Index', 'Cycle_Index', 'Is_FC_Data', 'Current', 'Voltage', 'Charge_Capacity', 'Discharge_Capacity', 'Charge_Energy', 'Discharge_Energy', 'dV/dt', 'Internal_Resistance', 'AC_Impedance', 'ACI_Phase_Angle']
    
    >>> n=header.index('Test_Time') 
    >>> by_time=sorted(databyrow,key=lambda t: t[n])
    

    【讨论】:

    • 打印时我在这里得到空输出(((
    • 打印输出的哪一部分?
    • 我正准备放弃那场战斗。不知道从 mdb 文件中排序表在 Python[] {} Traceback(最近一次调用最后)中会变得如此复杂:文件“dump3.py”,第 55 行,在 data_bycycle[1.0][-N :] KeyError: 1.0 基本上我只是得到一个空白屏幕。甚至之前的 Print 行也会产生空白输出。
    • dict data_bycycle 中有哪些键?试试print data_bycycle.keys()
    • 好的,开始时我尝试传递提取表的内容时出现某种错误。我刚刚打开了一个示例 .txt 文件并得到了一些输出。但最后我仍然收到错误 Traceback (最近一次调用最后): File "dump3.py", line 55, in data_bycycle[1.0][-N:] KeyError: 1.0
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-12-06
    • 2014-07-23
    • 2019-02-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多