У меня есть такой фрейм данных:
df <- data.frame(ID = c(1,2,3,4,5),
Total = c(1,1,2,1,2),
Ma = c(1,2,1,2,1),
Mb = c(1,2,1,2,2),
Md = c(1,2,1,2,1),
Me = c(1,1,1,2,2))
Я хотел бы добавить столбец, чтобы указать максимальную частоту повторения, от столбца Total до столбца Me для каждой строки. Это должно быть что-то вроде:
rep.rate = c(1,0.6,0.8,0.8,0.6)
Эти значения показывают частоту повторения наиболее распространенного значения в пяти столбцах каждой строки.





Можешь попробовать,
apply(df[-1], 1, function(i)max(prop.table(table(i))))
#[1] 1.0 0.6 0.8 0.8 0.6
library(dplyr)
df <- data.frame(ID = c(1,2,3,4,5), Total = c(1,1,2,1,2),
Ma = c(1,2,1,2,1), Mb = c(1,2,1,2,2),
Md = c(1,2,1,2,1), Me = c(1,1,1,2,2))
cat_mode <-
function(x){
cat_levels <- unique(x)
out <- cat_levels[which.max(tabulate(match(x, cat_levels)))]
return(out)
}
df %>%
rowwise() %>%
mutate(rep.rate = sum(c_across(Total:Me) == cat_mode(c_across(Total:Me)),na.rm =TRUE)/5)
# A tibble: 5 x 7
# Rowwise:
ID Total Ma Mb Md Me rep.rate
<dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 1 1 1 1 1 1 1
2 2 1 2 2 2 1 0.6
3 3 2 1 1 1 1 0.8
4 4 1 2 2 2 2 0.8
5 5 2 1 2 1 2 0.6
df <- data.frame(ID = c(1,2,3,4,5), Total = c(1,1,2,1,2),
Ma = c(1,2,1,2,1), Mb = c(1,2,1,2,2),
Md = c(1,2,1,2,1), Me = c(1,1,1,2,2))
library(dplyr, warn.conflicts = FALSE)
get_repeat_rate <- function(x){
table <- table(x)
props <- table/sum(table)
max_prop <- max(props)
return(max_prop)
}
df |>
rowwise() |>
mutate(repeat_rate = get_repeat_rate(c_across(-ID)))
#> # A tibble: 5 × 7
#> # Rowwise:
#> ID Total Ma Mb Md Me repeat_rate
#> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1 1 1 1 1 1 1 1
#> 2 2 1 2 2 2 1 0.6
#> 3 3 2 1 1 1 1 0.8
#> 4 4 1 2 2 2 2 0.8
#> 5 5 2 1 2 1 2 0.6
Created on 2023-01-24 with reprex v2.0.2
dplyr проблема. Ты прав, теперь все в порядке. очистка комментариев.
Вот более упрощенное dplyr решение, которому не нужна определяемая пользователем функция:
library(dplyr)
df %>%
rowwise %>%
mutate(rep.rate = max(table(c_across(-ID)))/(ncol(.)-1)) %>%
# mutate(rep.rate = max(proportions(table(c_across(-ID))))) ## alternative
ungroup
# # A tibble: 5 x 7
# ID Total Ma Mb Md Me rep.rate
# <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
# 1 1 1 1 1 1 1 1
# 2 2 1 2 2 2 1 0.6
# 3 3 2 1 1 1 1 0.8
# 4 4 1 2 2 2 2 0.8
# 5 5 2 1 2 1 2 0.6
Шаги для решения этой проблемы следующие:
df%>%
rowwise()%>%
mutate(rep.rate=sum(across(Total:Me)== max(Total:Me))/5)
rowwise() делает все операции построчными. Затем mutate используется для создания нового столбца, который соответствует следующему: max(Total:Me) находит максимальное значение. Затем sum(across(Total:Me)== max) находит, сколько вхождений максимального значения в текущей строке. Затем мы делим это число на 5, чтобы получить нужную пропорцию.
Если столбцы принимают только 2 значения, как в примере данных:
0.5 + abs(rowMeans(df[,-1] == df[1, 2]) - 0.5)
#> [1] 1.0 0.6 0.8 0.8 0.6
Если они принимают более 2 значений, векторизованное решение с использованием matrixStats::rowTabulates:
library(matrixStats)
rowMaxs(
rowTabulates(
matrix(
match(
unlist(df[,-1]),
unique(unlist(df[,-1]))
), nrow(df)
)
)
)/(ncol(df) - 1)
#> [1] 1.0 0.6 0.8 0.8 0.6
Вы пометили этот вопрос тегами dplyr и lapply. Вы специально ищете решения, использующие lapply и dplyr?