Как выбрать содержимое столбца на основе максимального значения в группах другого столбца. Выберите имя маркера на основе максимального значения для каждого гена - PullRequest
1 голос
/ 20 февраля 2020

У меня есть следующий df:

Gene pval  Marker
A      0.12     M1
A      0.11     M2
B      0.33     M3
B      0.55     M4
B      0.06     M5
D      0.03     M7
D      0.04     M8

Я хочу получить имя маркера на основе максимального значения pvalue для каждого гена. Что я пробовал:

peak_marker <-df[which.max(df[,2]),3]

Но в результате получается имя маркера с самым высоким значением pvalue во всем фрейме данных, а не имя маркера с самым высоким pval для каждого гена.

Я также попробовал это безуспешно:

aggregate(df$pval, by = list(df$Gene), which.max)

Ответы [ 3 ]

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

Вот решения, использующие как base, так и data.table!

Чтение в данных:

library(data.table)
df = fread("Gene pval  Marker
A      0.12     M1
A      0.11     M2
B      0.33     M3
B      0.55     M4
B      0.06     M5
D      0.03     M7
D      0.04     M8")
setDF(df)

С base мы, по сути, пройдем go через каждое уникальное значение для Gene и подмножество данных вручную

sapply(unique(df[,'Gene']), FUN = function(g) {
    d = df[df$Gene == g,]
    d[which.max(d[,2]),3]
})
#>    A    B    D 
#> "M1" "M4" "M8"

С помощью data.table мы можем использовать аргумент by, чтобы разбить данные на группы и затем получить доступ к части данных в группе используя .SD (который является подмножеством данных)

setDT(df)
df[,.SD[order(-pval)][1,Marker], by = Gene]
#>    Gene V1
#> 1:    A M1
#> 2:    B M4
#> 3:    D M8
0 голосов
/ 20 февраля 2020

На самом деле вы очень близки к тому, чтобы сделать это с aggregate, но вам, возможно, понадобится дополнительная помощь от merge.

Вот базовое решение R, где aggregate + merge были используется, то есть

dfout <- merge(aggregate(pval~Gene,df,max),df,all.x = T)

таким, что

> dfout
  Gene pval Marker
1    A 0.12     M1
2    B 0.55     M4
3    D 0.04     M8

ДАННЫЕ

df <- structure(list(Gene = c("A", "A", "B", "B", "B", "D", "D"), pval = c(0.12, 
0.11, 0.33, 0.55, 0.06, 0.03, 0.04), Marker = c("M1", "M2", "M3", 
"M4", "M5", "M7", "M8")), class = "data.frame", row.names = c(NA, 
-7L))
0 голосов
/ 20 февраля 2020

Решение с использованием dplyr:

library(dplyr)
df %>% 
  group_by(Gene) %>% 
  filter(val == max(val))

Возвращает:

  # A tibble: 3 x 3
  # Groups:   Gene [3]
    Gene    val Marker
    <chr> <dbl> <chr> 
  1 A      0.12 M1    
  2 B      0.55 M4    
  3 D      0.04 M8   

Или, если мы хотим избавиться от группировки:

  df %>% 
    group_by(Gene) %>% 
    filter(val == max(val)) %>% 
    ungroup()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...