У меня есть от 16 до 20 файлов (с разделителями табуляции / запятыми), каждый файл содержит 2 столбца. Столбцы, как показано ниже. 1. Интервал (мсек) 2. IOPS

Я хочу объединить все 20 файлов для ex:

Файл 1:

1000, 11217              
2000, 12789              
3001, 12022              
4000, 14028   

Файл 2:

1000, 11236
2000, 12789
3001, 12022
4000, 14028         

Таким образом, у меня есть 20 входных файлов. эти файлы будут созданы на основе потоков.

Выход должен быть как

1000, 11217, 11236
2000, 12789, 12803
3000, 12156
3001, 12022
4000, 14028, 13889

Может кто-нибудь, пожалуйста, предложите, какой будет лучший способ объединить файлы.

Благодарю вас заранее

0
Sindhu 28 Апр 2020 в 09:54

2 ответа

Лучший ответ

Чтобы протестировать приведенный ниже скрипт, я сгенерировал некоторые тестовые данные, а именно 16 файлов, каждый из которых содержит 12 записей, со случайным вхождением значений t, которые не совсем равны кратному 1000, используя следующий вспомогательный скрипт

from random import random, seed
seed(1234)

for n in range(1, 17):
    with open('f%02d'%n, 'w') as f:
        for t in range(1000,12001,1000):
            print(t+(1 if random()<0.1 else 0),int(random()*10000), sep=', ', file=f)

Например, файл f07 содержит

1000, 3812
2000, 9600
3000, 9210
4000, 6852
5000, 8387
6001, 2603
7000, 8578
8000, 1137
9000, 2138
10000, 5875
11001, 8774
12000, 7768

В следующем скрипте используется heapq.merge для заказа данные, которые поступают из отсортированных файлов, данные фильтруются простым генератором, который разбивает отдельную запись и добавляет информацию относительно файла, которому принадлежит запись, так что мы можем записывать единые записи, возможно, с пустыми записями.

Используйте debug = False, чтобы использовать скрипт для ваших данных.

'''Usage: python3 merge.py filename1, filename2, ..., filenameout'''
from heapq import merge
from sys import argv, stdout

def reader(fobj, n):
    for line in fobj:
        yield [x.strip() for x in line.split(',')]+[n]

# change to debug = False to run on your data
debug = True
argv = ['']+['f%02d'%n for n in range(1, 17)]+[''] if debug else argv
out  = stdout if debug else open(argv[-1], 'w')

readers = [reader(open(f), n) for n, f in enumerate(argv[1:-1])]
N = len(readers)

# header is "Interval,IOPS01,IOPS02,...,IOPSnn" modify as you like
print('Interval',*('IOPS%02d'%(n+1) for n in range(N)), sep=',', file=out)

# initialize for the loop
t0 = ""
# the loop
for t, iops, n in merge(*readers, key=lambda x:int(x[0])):
    if t != t0:
        if t0: print(t0, *iops_l, sep=',', file=out)
        t0 = t
        iops_l = ['····' if debug else '']*N
    iops_l[n] = '%4s'%iops if debug else iops

# the last record to output
print(t0, *iops_l, sep=',', file=out)

Запуск программы на f01, ..., f16 производит

Interval,IOPS01,IOPS02,IOPS03,IOPS04,IOPS05,IOPS06,IOPS07,IOPS08,IOPS09,IOPS10,IOPS11,IOPS12,IOPS13,IOPS14,IOPS15,IOPS16
1000,4407, 889,9569,2956, 477,5845,3812,3079,····,2571,4994,8863,6394,5339,8280,9311
1001,····,····,····,····,····,····,····,····,1400,····,····,····,····,····,····,····
2000,····,2695,3053,1856, 379,8128,9600,····,5880, 283,9501, 709,1964,5371,7242,3195
2001,9109,····,····,····,····,····,····,3949,····,····,····,····,····,····,····,····
3000,5822,6446,····,1194, 876,4995,9210,6827,7535,····,5323,8030,6204,3628,3730,5248
3001,····,····,2767,····,····,····,····,····,····,9906,····,····,····,····,····,····
4000, 839,3552,1773,8294,6993,5490,6852,4005,2986,6665,1455,9396,5018,7121,6750,9895
5000,2368,9335,9547,8177,9450,1309,8387,2812,3305,5156,2432,3797,9101,4568,8340,····
5001,····,····,····,····,····,····,····,····,····,····,····,····,····,····,····,1974
6000,····,5301,8338,6410,····,9253,····,6004,2937,5152,5064, 524, 495,8768,7844,3358
6001,7887,····,····,····,2574,····,2603,····,····,····,····,····,····,····,····,····
7000,6232,····,····,7026,····, 697,8578,5188,8142,····,7734, 801,4680,5435,5463,6949
7001,····,5081,3861,····,4263,····,····,····,····,7595,····,····,····,····,····,····
8000,1485,····,3417,1571,3966,  17,1137,4574,5340,6980,3265,9292,3717,1917,7696, 293
8001,····,1437,····,····,····,····,····,····,····,····,····,····,····,····,····,····
9000,1144,3773,4759,2693,8873,6382,2138,6598,3396,2195,5617,6769,7784,8677,6985,3160
10000,····,····,4708,8404,8185,1482,5875,7255,3210,6531,5991,6930,  87,9459,9566,····
10001,4867,5875,····,····,····,····,····,····,····,····,····,····,····,····,····, 556
11000, 645,5573,8815,7935,8586,4327,····,1037,7596,6827,3717,8642,9853,8470,3549,4239
11001,····,····,····,····,····,····,8774,····,····,····,····,····,····,····,····,····
12000,4658,9373,7810, 707,7024,2071,7768,7940,5482,5641,7628,3714,5999,7547,1883,9796

После того, как я заменил debug = True на debug = False, программу можно запустить следующим образом

$ python3 merge.py f01 f02 f03 f04 f05 f06 f07 f08 f09 f10 f11 f12 f13 f14 f15 f16 OUT
$ cat OUT
Interval,IOPS01,IOPS02,IOPS03,IOPS04,IOPS05,IOPS06,IOPS07,IOPS08,IOPS09,IOPS10,IOPS11,IOPS12,IOPS13,IOPS14,IOPS15,IOPS16
1000,4407, 889,9569,2956, 477,5845,3812,3079,,2571,4994,8863,6394,5339,8280,9311
1001,,,,,,,,,1400,,,,,,,
2000,,2695,3053,1856, 379,8128,9600,,5880, 283,9501, 709,1964,5371,7242,3195
2001,9109,,,,,,,3949,,,,,,,,
3000,5822,6446,,1194, 876,4995,9210,6827,7535,,5323,8030,6204,3628,3730,5248
3001,,,2767,,,,,,,9906,,,,,,
4000, 839,3552,1773,8294,6993,5490,6852,4005,2986,6665,1455,9396,5018,7121,6750,9895
5000,2368,9335,9547,8177,9450,1309,8387,2812,3305,5156,2432,3797,9101,4568,8340,
5001,,,,,,,,,,,,,,,,1974
6000,,5301,8338,6410,,9253,,6004,2937,5152,5064, 524, 495,8768,7844,3358
6001,7887,,,,2574,,2603,,,,,,,,,
7000,6232,,,7026,, 697,8578,5188,8142,,7734, 801,4680,5435,5463,6949
7001,,5081,3861,,4263,,,,,7595,,,,,,
8000,1485,,3417,1571,3966,  17,1137,4574,5340,6980,3265,9292,3717,1917,7696, 293
8001,,1437,,,,,,,,,,,,,,
9000,1144,3773,4759,2693,8873,6382,2138,6598,3396,2195,5617,6769,7784,8677,6985,3160
10000,,,4708,8404,8185,1482,5875,7255,3210,6531,5991,6930,  87,9459,9566,
10001,4867,5875,,,,,,,,,,,,,, 556
11000, 645,5573,8815,7935,8586,4327,,1037,7596,6827,3717,8642,9853,8470,3549,4239
11001,,,,,,,8774,,,,,,,,,
12000,4658,9373,7810, 707,7024,2071,7768,7940,5482,5641,7628,3714,5999,7547,1883,9796
$ 
0
gboffi 13 Май 2020 в 17:14

Это не ответ ... это скорее своего рода очень длинный отформатированный комментарий .


Когда у вас возникают проблемы такого рода, то есть другая сторона говорит, что все в порядке с их сценарием, и вы видите, что он не работает, вы можете догадаться, что в середине есть environment проблемы, их среда отличается от вашего ...

Что ВЫ можете сделать, чтобы решить проблему? принимая в качестве примера текущее состояние вашей проблемы

  1. посмотрим, что произойдет, когда вы воссоздаете их среду:

    • в новой папке (пожалуйста, не все на вашем рабочем столе) скопируйте вспомогательный скрипт from random import random, seed ...etc etc и скопируйте merge.py
    • запустить вспомогательный скрипт
    • убедитесь, что файлы примеров созданы правильно
    • запустить merge.py с debug=True

    если то, что вы получаете, - это то, что вам показали, то наверняка это ваша среда

  2. в новой папке, пожалуйста, новую папку,
    • скопируйте свои файлы данных и merge.py, отредактируйте merge.py и установите debug=False
    • запустите скрипт !python file1 file2 file3 output (с правильными именами файлов)
    • если это работает, это было что-то на вашем рабочем столе, что мешало (что? на данный момент, все равно, это работает в новой среде, и это все)
    • если это не работает, вы должны убедиться сами < UL>
    • edit merge.py и поместите print s, чтобы проверить, что на самом деле делает скрипт, относительно того, что скрипт должен делать и что он действительно делает, потому что вы испытали a несоответствие, и вы хотите понять причину этого ...
    • например, список argv, содержит ли он ожидаемые элементы? легко добавить for arg in argv: print(arg) в код и посмотреть, что вы получите: имя программы (argv[0]), имена входных файлов и, наконец, имя выходного файла

Чтобы помочь вам, я покажу вам отладочную версию скрипта, где скрипт будет выводить много подробностей о том, что он действительно делает, но, пожалуйста, попробуйте Трудно понять, что напечатано, почему оно было напечатано и каковы последствия, когда вы обнаружите проблему ...

Мы здесь

$ cat mergedbg.py
'''Usage: python3 merge.py filename1, filename2, ..., filenameout'''

from heapq import merge
from sys import argv, stdout

def reader(fobj, n):
    for line in fobj:
        yield [x.strip() for x in line.split(',')]+[n]

print('Contents of argv',
      *((n, arg) for n, arg in enumerate(argv)), sep='\n\t')

# open the files for reading
readers = []
for n, fname in enumerate(argv[1:-1]):
    try:
        print('Trying to open', fname, end='... ')
        readers.append(reader(open(fname), n))
        print('OK')
    except:
        print('oops, something went wrong!')

# open the file for writing
try:
    print('Trying to open', argv[-1], 'for writing', end='... ')
    out  = open(argv[-1], 'w')
    print('OK')
except:
    print('oops, something went wrong!')

N = len(readers)
print("About to loop over %d files"%N)

# header is "Interval,IOPS01,IOPS02,...,IOPSnn" modify as you like
print('Interval',*('IOPS%02d'%(n+1) for n in range(N)), sep=',', file=out)

# initialize 
t0, icount, ocount = "", 0, 0
for t, iops, n in merge(*readers, key=lambda t:int(t[0])):
    icount += 1
    print((icount, n, t, iops), end = '')
    if t != t0:
        if t0:
            ocount += 1
            print(t0, *iops_l, sep=',', file=out)
        t0 = t
        iops_l = ['']*N 
    iops_l[n] = iops

# the last record to output
ocount += 1
print(t0, *iops_l, sep=',', file=out)
# summary
print("\n%4d input records read,"%icount,
      "\n%4d output records written (1 header, %d data)."%(ocount+1, ocount))

Конечно, вы должны запустить скрипт с вашими именами файлов ...

$ python3 mergedbg.py f01 f02 f03 f04 OUTdbg
Contents of argv
        (0, 'mergedbg.py')
        (1, 'f01')
        (2, 'f02')
        (3, 'f03')
        (4, 'f04')
        (5, 'OUTdbg')
Trying to open f01... OK
Trying to open f02... OK
Trying to open f03... OK
Trying to open f04... OK
Trying to open OUTdbg for writing... OK
About to loop over 4 files
(1, 0, '1000', '4407')(2, 1, '1000', '889')(3, 2, '1000', '9569')(4, 3, '1000', '2956')(5, 1, '2000', '2695')(6, 2, '2000', '3053')(7, 3, '2000', '1856')(8, 0, '2001', '9109')(9, 0, '3000', '5822')(10, 1, '3000', '6446')(11, 3, '3000', '1194')(12, 2, '3001', '2767')(13, 0, '4000', '839')(14, 1, '4000', '3552')(15, 2, '4000', '1773')(16, 3, '4000', '8294')(17, 0, '5000', '2368')(18, 1, '5000', '9335')(19, 2, '5000', '9547')(20, 3, '5000', '8177')(21, 1, '6000', '5301')(22, 2, '6000', '8338')(23, 3, '6000', '6410')(24, 0, '6001', '7887')(25, 0, '7000', '6232')(26, 3, '7000', '7026')(27, 1, '7001', '5081')(28, 2, '7001', '3861')(29, 0, '8000', '1485')(30, 2, '8000', '3417')(31, 3, '8000', '1571')(32, 1, '8001', '1437')(33, 0, '9000', '1144')(34, 1, '9000', '3773')(35, 2, '9000', '4759')(36, 3, '9000', '2693')(37, 2, '10000', '4708')(38, 3, '10000', '8404')(39, 0, '10001', '4867')(40, 1, '10001', '5875')(41, 0, '11000', '645')(42, 1, '11000', '5573')(43, 2, '11000', '8815')(44, 3, '11000', '7935')(45, 0, '12000', '4658')(46, 1, '12000', '9373')(47, 2, '12000', '7810')(48, 3, '12000', '707')
  48 input records read, 
  19 output records written (1 header, 18 data).
$ cat OUTdbg 
Interval,IOPS01,IOPS02,IOPS03,IOPS04
1000,4407,889,9569,2956
2000,,2695,3053,1856
2001,9109,,,
3000,5822,6446,,1194
3001,,,2767,
4000,839,3552,1773,8294
5000,2368,9335,9547,8177
6000,,5301,8338,6410
6001,7887,,,
7000,6232,,,7026
7001,,5081,3861,
8000,1485,,3417,1571
8001,,1437,,
9000,1144,3773,4759,2693
10000,,,4708,8404
10001,4867,5875,,
11000,645,5573,8815,7935
12000,4658,9373,7810,707
$ 

В заключение, я полагаю, что между нами существует тривиальное недоразумение, и мне кажется, что мне трудно найти проблему ... Могу ли я честно предложить вам обратиться за помощью к вашему коллеге, даже с ограниченными знаниями Python, потому что это может быть очень полезно, они смотрят на ваш процесс через плечо и задают вам вопросы, пока вы идете, да, это может быть очень полезно.

Тем не менее, пожалуйста, задавайте мне другие вопросы, как вы хотите :-)

0
gboffi 14 Май 2020 в 10:44