Удалить строки, у которых определенный атрибут меньше или равен 0
У меня есть несколько больших текстовых файлов (30 м + строки, >1 ГБ), которые обрабатываются в ArcGIS после разделения (см. Удаление отдельных строк из большого текстового файла в python и разбиение текстовой базы данных на N равных блоков и сохранение заголовка для фона).
Даже после разделения процесс занимает более 3 дней, поэтому я хочу удалить все точки xy, у которых значение (Rx) меньше или равно 0.
У меня нет Python для работы над чтением наборов данных TXT более 500 МБ, поэтому я использовал команды Cygwin/SED для начальной очистки данных, а затем Python для порции файла. Поэтому в идеале процесс должен был бы добавить некоторый код в питон (см. Ниже), чтобы не включать все строки с Rx<=0.
Latitude Longitude Rx Best_Unit
-16.37617 144.68805 -012.9 7
-16.37617 144.68834 -015.1 7
-16.37617 144.68861 -017.2 7
-16.37617 144.68890 -018.1 7
-16.37617 144.68919 -025.0 7
-16.37617 144.68945 -019.5 7
-16.37617 144.68974 -020.0 7
-16.37617 144.69003 -020.4 7
-16.37617 144.69623 015.3 7
-16.37617 144.69652 015.6 7
-16.37617 144.69679 015.8 7
-16.37617 144.69708 016.0 7
-16.37617 144.70076 005.0 7
-16.37617 144.70103 002.2 7
-16.37617 144.70131 -000.2 7
-16.37617 144.70160 -001.5 7
-16.37617 144.70187 -001.0 7
-16.37617 144.70216 000.7 7
-16.37617 144.70245 002.2 7
-16.37617 144.70273 008.4 7
-16.37617 144.70300 017.1 7
-16.37617 144.70329 017.2 7
Я хочу, чтобы все строки (строки), где Rx>0, были записаны в новый текстовый файл. Я также хочу удалить столбец Best_Unit.
from itertools import islice
import arcpy, os
#fc = arcpy.GetParameter(0)
#chunk_size = arcpy.GetParameter(1) # number of records in each dataset
fc='cb_vhn007_5.txt'
Name = fc[:fc.rfind('.')]
fl = Name+'.txt'
headers_count = 1
chunk_size = 500000
with open(fl) as fin:
headers = list(islice(fin, headers_count))
part = 1
while True:
line_iter = islice(fin, chunk_size)
try:
first_line = line_iter.next()
except StopIteration:
break
with open(Name+'_%d.txt' % part, 'w') as fout:
for line in headers:
fout.write(line)
fout.write(first_line)
for line in line_iter:
## add something here to check if value after third tab
## is >0 and if so then write the row or skip.
fout.write(line)
print "Created part %d" % part
part += 1
Новый код - первая строка включает в себя - значения Rx.
from itertools import islice
import arcpy, os
#fc = arcpy.GetParameter(0)
#chunk_size = arcpy.GetParameter(1) # number of records in each dataset
fc='cb_vhn007_5.txt'
Name = fc[:fc.rfind('.')]
fl = Name+'.txt'
headers_count = 1
chunk_size = 500000
with open(fl) as fin:
headers = list(islice(fin, headers_count))
part = 1
while True:
line_iter = islice(fin, chunk_size)
try:
first_line = line_iter.next()
except StopIteration:
break
with open(Name+'_%d.txt' % part, 'w') as fout:
for line in headers:
fout.write(line)
fout.write(first_line)
for line in line_iter:
if line.split()[2][0:1] != '-':
#print line.split()[2]
fout.write(line)
print "Created part %d" % part
part += 1
5 ответов
Ты можешь использовать line.split()
разделить вашу строку в список, содержащий значение каждого из 4 столбцов.
Например:
line='-16.37617\t144.70329\t017.2\t7'
line.split()
# ['-16.37617', '144.70329', '017.2', '7']
Тогда вы можете заставить line[2]
(помните, что python - индексирование на основе 0) к числу и проверьте, является ли он> 0:
if float(line.split()[2]) > 0:
fout.write(line)
Или вы можете просто проверить, есть ли в нем знак минус:
if line.split()[2].find('-') != -1:
fout.write(line)
Если ваши столбцы могут быть не в том же порядке для каждого текстового файла, вы можете выполнить split()
по заголовкам определите, какой Rx
и используйте это вместо 2:
i = headers.split().index('Rx')
# now use line[i]
Наверное просто проверяю line_iter[24] != '-'
должно быть достаточно.
Т.е. заменить:
fout.write(line)
с
if line_iter[24] != '-':
fout.write(line)
Я знаю, что это не Python, но это, вероятно, правильный инструмент для работы:
cat cb_vhn007_5.txt | awk '($3 > 0) {print $0}' > parsedfile
Строки, которые вы ищете, примерно такие:
if line.split()[2][0:1] != "-"
fout.write(line)
Это разделяет ввод, просматривает третью запись, просматривает первый символ и пропускает печать строки, если это -
,
Вот скрипт Python, который будет читать файл, содержащий данные, отформатированные в виде четырех разделенных пробелами полей в строке, проверять третье поле и выводить любые строки, третье поле которых является положительным числом с плавающей запятой.
Протестировано работает на Python 2.7.2.
import re
in_fh = open ("gis.txt","r")
out_fh = open ("outfile.txt","w")
for row in in_fh:
row = re.sub(' +',',',row) # convert to comma-separated format
try:
latitude, longitude, rx, best_unit = row.split(',')
except ValueError: # row didn't have four fields
print ("complain - not four fields")
continue
try:
float_rx = float(rx)
except ValueError: # rx could not be cast to float
print ("complain - third field not float")
continue
if float_rx > 0:
out_fh.write(latitude + "," + longitude + "," + rx + "\n")
else:
pass # discard the row
in_fh.close()
out_fh.close()
Одновременно обрабатывается только одна строка, поэтому использование памяти должно быть постоянным независимо от размера входных и выходных файлов.
Альтернативно, вы рассматривали возможность использования базы данных? sqlite3
встроен и, вероятно, будет нормально обрабатывать 1 ГБ данных. Тогда вы могли бы получить этот результат, выполнив SELECT * FROM data WHERE rx > 0
,