Как разбить кадр данных по строкам, а затем обработать блоки?

У меня есть кадр данных с несколькими столбцами, один из которых является фактором, называемым "сайтом". Как я могу разделить фрейм данных на блоки строк с уникальным значением "сайт", а затем обработать каждый блок с помощью функции? Данные выглядят следующим образом:

site year peak
ALBEN 5 101529.6
ALBEN 10 117483.4
ALBEN 20 132960.9
ALBEN 50 153251.2
ALBEN 100 168647.8
ALBEN 200 184153.6
ALBEN 500 204866.5
ALDER 5 6561.3
ALDER 10 7897.1
ALDER 20 9208.1
ALDER 50 10949.3
ALDER 100 12287.6
ALDER 200 13650.2
ALDER 500 15493.6
AMERI 5 43656.5
AMERI 10 51475.3
AMERI 20 58854.4
AMERI 50 68233.3
AMERI 100 75135.9
AMERI 200 81908.3

и я хочу создать график year vs peak для каждого сайта.

Ответ 1

Другой вариант - использовать функцию ddply из библиотеки ggplot2. Но вы упоминаете, что в основном хотите построить график пиковых и qplot, поэтому вы также можете просто использовать qplot:

A <- read.table("example.txt",header=TRUE)
library(ggplot2)
qplot(peak,year,data=A,colour=site,geom="line",group=site)
ggsave("peak-year-comparison.png")

alt text

С другой стороны, мне нравится решение Дэвида Смита, которое позволяет применять эту функцию на нескольких процессорах.

Ответ 2

Вы можете использовать isplit (из пакета "итераторы" ), чтобы создать объект-итератор, который перебирает блоки, определенные столбцом site:

require(iterators)
site.data <- read.table("isplit-data.txt",header=T) 
sites <- isplit(site.data,site.data$site)

Затем вы можете использовать foreach (из пакета foreach) для создания графика внутри каждого блока:

require(foreach)
foreach(site=sites) %dopar% {
 pdf(paste(site$key[[1]],".pdf",sep=""))
 plot(site$value$year,site$value$peak,main=site$key[[1]])
 dev.off()
}

В качестве бонуса, если у вас есть многопроцессорная машина и сначала вызов registerDoMC() (из пакета "doMC" ), циклы будут работать параллельно, ускоряя работу. Подробнее в этом сообщении в блоге Revolutions: Блокировка кадра данных с помощью isplit

Ответ 3

Мне кажется, что обычный старый split() имеет метод для data.frames, так что split(data,data$site) создаст список блоков. Затем вы можете использовать этот список, используя sapply/lapply/for.

split() также хорош из-за unsplit(), который создаст вектор такой же длины, что и исходные данные и в правильном порядке.

Ответ 4

Вот что я буду делать, хотя, похоже, вы, ребята, справились с библиотечными функциями.

for(i in 1:length(unique(data$site))){
  constrainedData = data[data$site==data$site[i]];
  doSomething(constrainedData);
}

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

Ответ 5

Есть две удобные встроенные функции для работы с такими ситуациями.? aggregate и? by. В этом случае, поскольку вы хотите построить график и не возвращаете скаляр, используйте()

data <- read.table("example.txt",header=TRUE)

by(data[, c('year', 'peak')], data$site, plot)

На выходе написано NULL, потому что этот сюжет возвращается. Возможно, вы захотите установить графическое устройство в pdf, чтобы захватить весь вывод.

Ответ 6

Также очень легко сгенерировать ваши графики с помощью пакета решетки:

library(lattice)
xyplot(year~peak | site, data)

Ответ 7

Вы можете использовать функцию split Если вы открыли свои данные как:

data <- read.table('your_data.txt', header=T)
blocks <- split(data, data$site)

После этого блоки содержат данные из каждого блока, к которым вы можете получить доступ, как другие data.frame:

plot(blocks$ALBEN$year, blocks$ALBEN$peak)

И так далее для каждого сюжета.