Получение процента от каждого объекта .map - PullRequest
0 голосов
/ 21 февраля 2020

У меня есть строка символов, каждому символу присваивается вес с использованием блока if внутри al oop (.map). Я инициализировал общее значение за пределами l oop total_weight = 0. но поскольку это значение находится за пределами l oop, оно меняется с каждой итерацией. Я не уверен, как использовать total_weight для расчета процента веса для каждого символа, так как вес символа эффективен только внутри l oop, а total_weight эффективен только за пределами l oop, как только он имеет фактический итог вес для всей строки.

sequence ="AAGCAAGTCCATACGAATATGGCACTAGATCTTGAAGGGAAGTATTTTTTCTACTTTATGGTTAAATAGCTATGATTGAAAGAGTGTAATTGTCAT"


total_weight = 0

char_count =sequence.each_char.tally
puts "length of sequence is #{sequence.length}"

char_count.map do |seq_letter , seq_letter_frequency , weight|
  puts
  puts "there are #{seq_letter_frequency} #{seq_letter} in this sequence"

  if    seq_letter == "A"  ; weight = 331.0

  elsif seq_letter == "T"  ; weight = 321.0

  elsif seq_letter == "G"  ; weight = 347.0

  elsif seq_letter == "C"  ; weight = 307.0

  end
  seq_letter_sum_weight = weight * seq_letter_frequency.to_f

  total_weight += seq_letter_sum_weight

  puts "total_weight keeps changing??? #{total_weight}"

  seq_letter_percent_by_weight = (seq_letter_sum_weight/total_weight) *100.0

  puts
  puts "#{seq_letter} occurs at a #{seq_letter_percent_by_weight}%" # outputted % is incorrect due to the changing @total_weight in the denominator

end




Кроме того, возможно ли сохранить решение в пределах l oop?

Ответы [ 3 ]

1 голос
/ 21 февраля 2020

Здесь вам не нужен l oop, предоставляет все инструменты для более удобного вычисления.

weights = {"A" => 331.0, "T" => 321.0, "G" => 347.0, "C" => 307.0}
sequence ="AAGCAAGTCCATACGAATATGGCACTAGATCTTGAAGGGAAGTATTTTTTCTACTTTATGGTTAAATAGCTATGATTGAAAGAGTGTAATTGTCAT"

total = sequence.length 
total_weights = weights.sum { |l, w| sequence.count(l).to_f / total * w }
#⇒ 328.1458333333333
0 голосов
/ 21 февраля 2020

Вот мое взятие при расчете веса каждого присутствующего символа в строке:

sequence = 'AAGCAAGTCCATACGAATATGGCACTAGATCTTGAAGGGAAGTATTTTTTCTACTTTATGGTTAAATAGCTATGATTGAAAGAGTGTAATTGTCAT'
weights = {A: 331.0, T: 321.0, G: 347.0, C: 307.0}
results = weights.map{ |k, v| [k, sequence.count(k.to_s) * v] }.to_h
total_weight = results.values.sum
results.each {|k, v| puts "#{k} occurs at a #{(100 * v / total_weight).round(2)}%"}

Это дает следующие результаты:

A происходит при 33,62%

Т происходит при 33,63%

Г происходит при 22,03%

C происходит при 10,72%

0 голосов
/ 21 февраля 2020

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

weights = {"A" => 331.0, "T" => 321.0, "G" => 347.0, "C" => 307.0}

sequence.each_char.
         tally.
         map { |c,n| n*weights[c] }.
         sum.
         fdiv(weights.values.sum)
  #=> 24.120980091883613

Обратите внимание, что Enumerable # tally дебютировал в Ruby v2.7.

Шаги следующие:

e = sequence.each_char
  #=> #<Enumerator: "AAGCA...CAT":each_char>

Мы можем преобразовать этот перечислитель в массив, чтобы увидеть значения, которые он сгенерирует, и передать tally.

e.to_a
  #=> ["A", "A", "G", "C", "A",..., "C", "A", "T"] 

Продолжая,

h = e.tally
  #=> {"A"=>32, "G"=>20, "C"=>11, "T"=>33} 
a = h.map { |c,n| n*weights[c] }
  #=> [10592.0, 6940.0, 3377.0, 10593.0] 
t = a.sum
  #=> 31502.0
b = weights.values.sum
  #=> 1306.0 
t.fdiv(b)
  #=> 24.120980091883613 

Обратите внимание, что если бы веса были равны, это вычислило бы простое среднее значений h.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...