2013-03-04 3 views
1

У меня есть файл, подобный этому ниже.Python: прочитайте файл и замените его по строке определенным условием

0  0  0 
0.00254 0.00047 0.00089 
0.54230 0.87300 0.74500 
0  0  0 

Я хочу изменить этот файл. Если значение меньше 0,05, то значение должно быть равно 1. В противном случае значение должно быть 0.

После запуска питон скрипт, файл должен быть как

1  1  1 
1  1  1 
0  0  0 
1  1  1 

бы вы, пожалуйста, помогите меня?

+7

Интересная проблема и очень легко решить. В какой момент вы точно застреваете? –

+2

У вас проблемы с чтением файла? Разбор данных? Запись в файл? – thegrinner

ответ

1

Вы можете использовать этот код

f_in=open("file_in.txt", "r")  #opens a file in the reading mode 
in_lines=f_in.readlines()   #reads it line by line 
out=[] 
for line in in_lines: 
    list_values=line.split()  #separate elements by the spaces, returning a list with the numbers as strings 
    for i in range(len(list_values)): 
     list_values[i]=eval(list_values[i])  #converts them to floats 
#  print list_values[i], 
     if list_values[i]<0.05:  #your condition 
#   print ">>", 1 
      list_values[i]=1 
     else: 
#   print ">>", 0 
      list_values[i]=0 
    out.append(list_values)   #stores the numbers in a list, where each list corresponds to a lines' content 
f_in.close()      #closes the file 

f_out=open("file_out.txt", "w")  #opens a new file in the writing mode 
for cur_list in out: 
    for i in cur_list: 
     f_out.write(str(i)+"\t") #writes each number, plus a tab 
    f_out.write("\n")    #writes a newline 
f_out.close()      #closes the file 
3

ОК, так как вы новичок в StackOverflow (добро пожаловать!) Я проведу вас через это. Я предполагаю, что ваш файл называется test.txt.

with open("test.txt") as infile, open("new.txt", "w") as outfile: 

открывает необходимые файлы, наш входной файл и новый выходной файл. Оператор with гарантирует, что файлы будут закрыты после выхода из блока.

for line in infile: 

петли через файл по строкам.

 values = [float(value) for value in line.split()] 

Теперь это сложнее. Каждая строка содержит значения, разделенные пробелами. Их можно разбить на список строк, используя line.split(). Но они все еще строки, поэтому их нужно сначала преобразовать в float. Все это делается со списком. В результате, например, после того, как вторая строка была обработана таким образом, values теперь выглядит следующим образом: [0.00254, 0.00047, 0.00089].

 results = ["1" if value < 0.05 else "0" for value in values] 

Теперь мы создаем новый список под названием results. Каждый элемент соответствует элементу values, и он будет "1", если это value < 0.05, или "0", если это не так.

 outfile.write("  ".join(results)) 

преобразовывает список «целых строк» ​​обратно в строку, разделенную 7 пробелами каждый.

 outfile.write("\n") 

добавляет новую строку. Готово.


Два списочные могут быть объединены в один, если вы не возражаете дополнительные сложности:

 results = ["1" if float(value) < 0.05 else "0" for value in line.split()] 
2

, если вы можете использовать библиотеки, я хотел бы предложить NumPy:

import numpy as np 
myarray = np.genfromtxt("my_path_to_text_file.txt") 
my_shape = myarray.shape() 
out_array = np.where(my_array < 0.05, 1, 0) 
np.savetxt(out_array) 

Вы можете добавить форматирование в качестве аргументов функции savetxt. Докстоны функции довольно понятны.

Если вы застряли с чистым питона:

with open("my_path_to_text_file") as my_file: 
    list_of_lines = my_file.readlines() 
    list_of_lines = [[int(float(x) < 0.05) for x in line.split()] for line in list_of_lines] 

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

+0

oups! Спасибо. Служит мне для публикации кода, который я не запускал. –

0

Следующий код выполняет замену в месте: для этого файл открыт в режиме 'rb+'. Это абсолютно необходимо открыть в двоичном режиме b. + в 'rb+' означает, что запись и чтение можно записать в файл. Обратите внимание, что режим можно также написать 'r+b'.

Но использование 'rb+' неудобно:

  • если вы читаете с for line in f, файл читается кусками и несколько строк, не сохраняются в буфере, где они на самом деле читать одну за другой, пока другой кусок данных считывается и загружается в буфер. Это затрудняет выполнение преобразований, потому что нужно следовать указателю файла с помощью tell() и перемещать указатель с seek(), и на самом деле я не полностью понял, как это должно быть сделано.
    .
    К счастью, есть решение с replace(), потому что, я не знаю почему, но я верю в факты, когдачитает строку, указатель файла не идет дальше на диске, чем конец строки (то есть он останавливается на новой строке).
    Теперь это легко перемещать и знать позиции указателя файла в

  • сделать запись после чтения, необходимо сделать seek() выполняется, даже если он должен быть сделать seek(0,1), что означает переход от 0 caracters от фактическое положение. Это должно изменить состояние указателя файла, что-то вроде этого.

Ну, для Вашей проблемы, код выглядит следующим образом:

import re 
from os import fsync 
from os.path import getsize 

reg = re.compile('[\d.]+') 

def ripl(m): 
    g = m.group() 
    return ('1' if float(g)<0.5 else '0').ljust(len(g)) 

path = ...........' 

print 'length of file before : %d' % getsize(path) 

with open('Copie de tixti.txt','rb+') as f: 
    line = 'go' 
    while line: 
     line = f.readline() 
     lg = len(line) 
     f.seek(-lg,1) 
     f.write(reg.sub(ripl,line)) 
     f.flush() 
     fsync(f.fileno()) 

print 'length of file after : %d' % getsize(path) 

flush() и fsync() должны быть выполнены для того, чтобы команда f.write(reg.sub(ripl,line)) эффективно пишет на данный момент она ordred к.

Обратите внимание: я никогда не управлял файлом, закодированным в юникоде. Это, безусловно, еще больше, так как каждый символ Юникода закодирован на несколько байтов (и в случае UTF8, переменное количество байтов в зависимости от символа)

Смежные вопросы