2014-01-21 8 views
2

У меня есть кадр данных, который содержит числовые значения 1: 4 с некоторыми NA. Для каждой строки я хотел бы рассчитать частоту (в процентах) от значения с наименьшим количеством событий, превышающим 0.Найти минимальное значение больше 0

Вот пример кадра данных для работы.

df = as.data.frame(rbind(c(1,2,1,2,2,2,2,1,NA,2),c(2,3,3,2,3,3,NA,2,NA,NA),c(4,1,NA,NA,NA,1,1,1,4,4),c(3,3,3,4,4,4,NA,4,3,4))) 

     V1 V2 V3 V4 V5 V6 V7 V8 V9 V10 
    1 1 2 1 2 2 2 2 1 NA 2 
    2 2 3 3 2 3 3 NA 2 NA NA 
    3 4 1 NA NA NA 1 1 1 4 4 
    4 3 3 3 4 4 4 NA 4 3 4 

У меня есть 2 очка, с которыми я борюсь. 1) поиск самой низкой частоты значения больше 0 и 2) применения функции к каждой строке моего кадра данных. Когда я начал работать над этой функцией, я реализовал ее с использованием кода ниже, но, похоже, не применялся к каждой строке. Мой результат для value.1, value.2 и т. Д. Был одинаковым для каждой строки.

Low_Freq = function(x){ 
     value.1 = sum(x==1, na.rm=TRUE) #count the number of 1's per row 
     value.2 = sum(x==2, na.rm=TRUE) #count the number of 2's per row 
     value.3 = sum(x==3, na.rm=TRUE) #count the number of 3's per row 
     value.4 = sum(x==4, na.rm=TRUE) #count the number of 4's per row 
     num.values = rowSums(!is.na(x), na.rm=TRUE) #count total number of non-NA values in each row 

     #what is the minimum frequency value greater than 0 among value.1, value.2, value.3, and value.4 for EACH row? 
     min.value.freq = min(cbind(value.1,value.2,value.3,value.4)) 

     out = min.value.freq/num.values #calculate the percentage of the minimum value for each row 
    } 

    df$Low_Freq = apply(df, 1, function(x)) 

Тогда я начал использовать rowSums() для вычисления значения.1, value.2, value.3 и value.4. Это фиксированная моя проблема подсчета значения.1, value.2 и т.д. для каждой строки, однако, я тогда должен был применить функцию без использования применить() для его запуска:

Low_Freq = function(x){ 
     value.1 = rowSums(x==1, na.rm=TRUE) #count the number of 1's per row 
     value.2 = rowSums(x==2, na.rm=TRUE) #count the number of 2's per row 
     value.3 = rowSums(x==3, na.rm=TRUE) #count the number of 3's per row 
     value.4 = rowSums(x==4, na.rm=TRUE) #count the number of 4's per row 
     num.values = rowSums(!is.na(x), na.rm=TRUE) #count total number of non-NA values in each row 

     #what is the minimum frequency value greater than 0 among value.1, value.2, value.3, and value.4 for EACH row? 
     min.value.freq = min(cbind(value.1,value.2,value.3,value.4)) 

     out = min.value.freq/num.values #calculate the percentage of the minimum value for each row 
    } 

    df$Low_Freq = Low_Freq(df) 

So акте применения к каждой строке, то, казалось, происходило внутри самой функции. Все в порядке и денди, но когда я собираюсь сделать свой окончательный расчет, который будет моим выходом, я не могу понять, как определить, какие из значений 1, 2, 3 или 4 имеют самую низкую частоту для каждой строки. Это значение должно быть разделено на количество значений не-NA для каждой строки.

Мой желаемый результат должен выглядеть следующим образом:

 V1 V2 V3 V4 V5 V6 V7 V8 V9 V10 Low_Freq 
    1 1 2 1 2 2 2 2 1 NA 2 0.3333333 
    2 2 3 3 2 3 3 NA 2 NA NA 0.4285714 
    3 4 1 NA NA NA 1 1 1 4 4 0.4285714 
    4 3 3 3 4 4 4 NA 4 3 4 0.4444444 

Я чувствую, что я иду по кругу с этим, казалось бы, простой функции. Любая помощь будет оценена по достоинству.

спасибо.

ответ

3

Функция table возвращает частоту каждого отображаемого значения, игнорируя значения NA. Следовательно, min результата table - это минимальная частота значения, которое отображается в вашей строке, а сумма - это количество значений не NA в вашей строке.

Low_Freq = function(x){ 
    tab = table(x) 
    return(min(tab)/sum(tab)) 
} 
df$Low_Freq = apply(df, 1, Low_Freq) 
df 
# V1 V2 V3 V4 V5 V6 V7 V8 V9 V10 Low_Freq 
# 1 1 2 1 2 2 2 2 1 NA 2 0.3333333 
# 2 2 3 3 2 3 3 NA 2 NA NA 0.4285714 
# 3 4 1 NA NA NA 1 1 1 4 4 0.4285714 
# 4 3 3 3 4 4 4 NA 4 3 4 0.4444444 

Если вы хотите, чтобы не использовать 5s для числителя, но использовать их для знаменателя, вы можете сделать:

df = as.data.frame(rbind(c(1,2,1,2,2,2,2,1,NA,2),c(2,3,3,2,3,3,NA,2,NA,NA),c(4,1,NA,NA,NA,1,1,1,4,4),c(3,3,3,4,4,4,5,4,3,4))) 
Low_Freq = function(x){ 
    tab = table(x[x != 5]) 
    return(min(tab)/sum(!is.na(x))) 
} 
df$Low_Freq = apply(df, 1, Low_Freq) 
df 
# V1 V2 V3 V4 V5 V6 V7 V8 V9 V10 Low_Freq 
# 1 1 2 1 2 2 2 2 1 NA 2 0.3333333 
# 2 2 3 3 2 3 3 NA 2 NA NA 0.4285714 
# 3 4 1 NA NA NA 1 1 1 4 4 0.4285714 
# 4 3 3 3 4 4 4 5 4 3 4 0.4000000 
+0

Спасибо за ответ. Как я могу изменить это в случае, когда у меня есть одно вхождение числа «5» в двух из строк, и я хочу использовать только min freq чисел 1,2,3 и 4; но общее число, на которое делится число, должно быть равно количеству значений не-NA (включая 5)? – SC2

+0

@ SC2 Я обновил эту новую функциональность – josliber

+0

Красивая, спасибо вам большое! – SC2

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