2009-09-08 2 views
10

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

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 против peak для каждого сайта.

ответ

12

Другой вариант - использовать функцию ddply из библиотеки ggplot2. Но вы сказали, вы в основном хотят, чтобы сделать сюжет пика по сравнению год, так что вы можете просто использовать 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 http://i32.tinypic.com/16nuza.png

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

14

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

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

Затем вы можете использовать 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: Block-processing a data frame with isplit

4

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

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

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

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

6

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

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

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

+1

Карл, я согласен, что это читаемо. Но код для построения ('doSomething') будет намного меньше. Хорошее решение для другой проблемы imho. – isomorphismes

10

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

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

2

Это также очень легко создавать свои участки с пакетом решетки:

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

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

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

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

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

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