#r #dataframe #row #simplify
#r #фрейм данных #строка #упрощение
Вопрос:
У меня есть набор из 15 фреймов данных, связанных с последовательностями белков, и моя цель — проанализировать изменения в белках с течением времени. Однако мои фреймы данных содержат около 5000 генов. Итак, я ищу способ упростить свои данные для упрощения анализа.
Ниже приведен пример фрейма данных.
> sample
p1 p2 p3 year
1 a d d 1970
2 a c e 1970
3 b d e 1970
4 b c d 1985
5 b c d 1985
6 b c d 1999
Что я хочу сделать, так это анализировать каждую позицию ( p1
p2
и p3
) каждый год и возвращать наиболее распространенную запись в этой позиции в этом году и, таким образом, создавать новый фрейм данных только с одной последовательностью в год. Результирующий фрейм данных должен выглядеть как приведенный ниже пример:
> result
p1 p2 p3 year
1 a d e 1970
2 b c d 1985
3 b c d 1999
Фреймы данных уже отсортированы по дате, однако я не знаю, сколько записей в каждом году. Итак, есть ли способ упростить мои данные с помощью этого метода?
Ответ №1:
Решение data.table:
dat <- read.table(text=' p1 p2 p3 year
1 a d d 1970
2 a c e 1970
3 b d e 1970
4 b c d 1985
5 b c d 1985
6 b c d 1999',header=TRUE)
library(data.table)
DT <- as.data.table(dat)
DT[,lapply(.SD,function(x){ y = table(x)
names(y)[which.max(y)]}),
year]
# year p1 p2 p3
# 1: 1970 a d e
# 2: 1985 b c d
# 3: 1999 b c d
ОТРЕДАКТИРУЙТЕ другое базовое решение R:
do.call(rbind.data.frame,by(dat, dat$year, function(x)
lapply(x, function(y) {
t <- table(y)
names(t)[which.max(t)]
})))
# p1 p2 p3 year
# 1970 a d e 1970
# 1985 b c d 1985
# 1999 b c d 1999
Ответ №2:
Используя только базовые функции R, вы можете решить эту проблему следующим образом.
as.data.frame(t(
sapply(split(sample, sample$year), function(x) {
# for each x - data frame subset such grouped by year
apply(x, 2, function(y) {
# for each y, i.e. column in x
t <- table(y)
names(t)[which.max(t)] # return the label that occurs most often
})
})
))
Результат:
## p1 p2 p3 year
## 1970 a d e 1970
## 1985 b c d 1985
## 1999 b c d 1999
Комментарии:
1. 1 ! потому что все остальные решения — это просто переписывание этого. Я предлагаю использовать
by
для заменыsapply split
, избегать такжеapply
, чтобы избежать принуждения к символам… смотрите мое базовое решение R выше.2. Использование этой базовой функции выдало мне код ошибки, в котором говорилось
In split.default(x = seq_len(nrow(x)), f = f, drop = drop, ...) : data length is not a multiple of split variable
, что, однако, другая базовая операция R (от agstudy) работала отлично, поэтому я буду работать с ней…
Ответ №3:
Используя dplyr
вы могли бы сделать это следующим образом:
require(dplyr)
sample %>%
group_by(year) %>%
summarise_each(funs(names(which.max(table(.)))))
или
sample %>%
group_by(year) %>%
summarise(p1 = names(which.max(table(p1))),
p2 = names(which.max(table(p2))),
p3 = names(which.max(table(p3))))
Результат в обоих случаях:
# year p1 p2 p3
#1 1970 a d e
#2 1985 b c d
#3 1999 b c d
Первый метод является хорошим выбором, если у вас много столбцов, и вы хотите выполнить ту же операцию для всех этих столбцов, кроме переменной группировки (в данном случае year ). Второй метод подходит, если у вас меньше столбцов. По сути, они делают то же самое.
Редактировать
С помощью summarise_each
вы также можете указать столбцы, которые вы либо не хотите включать в операцию, либо которые вы хотите включить (и исключить все остальные столбцы). Итак, представьте, что в вашем образце данных было 100 столбцов p1 … p100, и вы хотите сделать это для всех столбцов, кроме p1 и p3, вы могли бы указать:
sample %>%
group_by(year) %>%
summarise_each(funs(names(which.max(table(.)))), -c(p1, p3))
С другой стороны, вы могли бы указать, чтобы это делалось только для этих двух столбцов:
sample %>%
group_by(year) %>%
summarise_each(funs(names(which.max(table(.)))), p1, p3)
И вы можете добавить больше функций к funs
аргументу внутри summarise_each
.
Комментарии:
1. 1 для использования
summarise_each
, стоит упомянуть, что вы также можете объединить его с фильтром, если хотите обработать все столбцы, кроме некоторых. Я все еще предпочитаю.SD
здесь, он более гибкий 🙂2. Спасибо за совет, фреймы данных, которые у меня есть, имеют разное количество столбцов (от 6 до 23), и я думаю, что в этом случае первый метод будет проще, поскольку я использую один код для всех фреймов данных