#r #aggregate
#r #агрегировать
Вопрос:
У меня возникают трудности с использованием непарного t-теста и агрегатной функции.
Пример
dd<-data.frame(names=c("1st","1st","1st","1st","2nd","2nd","2nd","2nd"),a=c(11,12,13,14,2.1,2.2,2.3,2.4),b=c(3.1,3.2,3.3,3.4,3.1,3.2,3.3,3.4))
dd
# Compare all the values in the "a" column that match with "1st" against the values in the "b" column that match "1st".
# Then, do the same thing with those matching "2nd"
t.test(c(11,12,13,14),c(3.1,3.2,3.3,3.4))$p.value
t.test(c(3.1,3.2,3.3,3.4),c(3.1,3.2,3.3,3.4))$p.value
# Also need to replace any errors from t.test that have too low variance with NA
# An example of the type of error I might run into would be if the "b" column was replaced with c(3,3,3,3,3,3,3,3).
Для парных данных я нашел обходной путь.
# Create Paired data.
data_paired<-dd[,3]-dd[,2]
# Create new t-test so that it doesn't crash upon the first instance of an error.
my_t.test<-function(x){
A<-try(t.test(x), silent=TRUE)
if (is(A, "try-error")) return(NA) else return(A$p.value)
}
# Use aggregate with new t-test.
aggregate(data_paired, by=list(dd$name),FUN=my_t.test)
Этот агрегат работает с одним столбцом входных данных. Однако я не могу заставить ее функционировать, когда мне нужно, чтобы в функцию входило несколько столбцов.
Пример:
my_t.test2<-function(x,y){
A<-try(t.test(x,y,paired=FALSE), silent=TRUE)
if (is(A, "try-error")) return(NA) else return(A$p.value)
}
aggregate(dd[,c(2,3)],by=list(dd$name),function(x,y) my_t.test2(dd[,3],dd[,2]))
Я думал, что агрегатная функция отправит только строки, соответствующие значению в списке, в функцию my_t.test2, а затем перейдет к следующему элементу списка. Однако полученные результаты указывают на то, что он выполняет t-тест для всех значений в столбце, как показано ниже. И затем поместите каждое из этих значений в результаты.
t.test(dd[,3],dd[,2])$p.value
Чего мне не хватает? Это проблемы с исходным my_test.2, проблема с тем, как структурировать агрегатную функцию, или что-то еще. То, как я ее применил, похоже, не агрегирует.
Это результаты, которые я хочу.
t.test(c(11,12,13,14),c(3.1,3.2,3.3,3.4))$p.value
t.test(c(3.1,3.2,3.3,3.4),c(3.1,3.2,3.3,3.4))$p.value
Обратите внимание, что это игрушечный пример, и фактический набор данных будет содержать более 100 000 записей, которые необходимо сгруппировать по значению в столбце имен. Следовательно, почему мне нужна агрегатная функция.
Спасибо за помощь.
Комментарии:
1. Вы говорите, что хотите сопоставить A-first с B-first, но
t.test(c(11,12,13,14),c(2.1,2.2,2.3,2.4))$p.value
это проверка A-first с A-second, верно? Это опечатка?2. Да, это была опечатка. Исправил это.
Ответ №1:
aggregate
это неправильная функция для использования здесь, потому что функция summary работает только с одним столбцом за раз. Невозможно получить оба a
и b
значения одновременно с помощью этого метода.
Другой способ, которым вы могли бы подойти к проблеме, — разделить данные, а затем применить t-тест к каждому подмножеству. Вот одна реализация
sapply(
split(dd[-1], dd$names),
function(x) t.test(x[["a"]], x[["b"]])$p.value
)
Здесь я разделяю dd
на список подмножеств для каждого значения names
. Я использую dd[-1]
для удаления столбца «имена» из подмножеств, чтобы у меня был просто data.frame с двумя столбцами. Один для a
и один для b
.
Затем для каждого подмножества в списке я выполняю a, t.test
используя столбцы a
и b
. Затем я извлекаю p-значение. sapply
Оболочка с вычислением этого p-значения для каждого подмножества и rill вернула именованный вектор p-значений, где имена записей соответствуют уровням dd$names
1st 2nd
6.727462e-04 3.436403e-05
Если вы хотите выполнить парный t-тест таким образом, вы могли бы сделать
sapply(
split(dd[-1], dd$names),
function(x) t.test(x[["a"]] - x[["b"]])$p.value
)
Комментарии:
1. Спасибо, пока это работает. Я немного незнаком с созданием объектов списка в R. Возможно, вы знаете, насколько сильно пострадает память для очень большого объекта списка по сравнению с фреймом данных?
Ответ №2:
Как сказал @MrFlick, agregate
это неправильная функция для этого. Вот несколько альтернатив подходу sapply с использованием пакетов dplyr
или data.table
.
require(dplyr)
summarize(group_by(dd, names), t.test(a,b)$p.value)
require(data.table)
data.table(dd)[, t.test(a,b)$p.value, by=names]