If you read the data in using limma, you already get some annotation. As an example, using GSE86970:
> dat <- read.maimages(fls, "agilent.median", green.only = TRUE) Read GSM2311277_V7T.txt Read GSM2311278_V8T.txt Read GSM2311279_V9T.txt Read GSM2311280_V12T.txt Read GSM2311281_V13T.txt Read GSM2311282_V15T.txt Read GSM2311283_V18T.txt Read GSM2311284_V20T.txt Read GSM2311285_V21T.txt Read GSM2311286_V24T.txt Read GSM2311287_V25T.txt Read GSM2311288_V27T.txt Read GSM2311289_V30T.txt Read GSM2311290_V33T.txt Read GSM2311291_V34T.txt Read GSM2311292_V39T.txt Read GSM2311293_V40T.txt > head(dat$genes[dat$genes$ControlType == 0,]) Row Col ControlType ProbeName SystematicName 4 1 4 0 A_23_P117082 NM_015987 5 1 5 0 A_33_P3246448 NM_080671 6 1 6 0 A_33_P3318220 NM_178466 7 1 7 0 A_33_P3236322 AK128005 8 1 8 0 A_33_P3319925 ENST00000449753 9 1 9 0 A_21_P0000509 NR_024244
The SystematicName is now a mixture of RefSeq and GenBank IDs, Ensembl transcript IDs, which would be a bit of a drag to annotate. Luckily others have already done that for you. We can get the GPL for this array from GEO as well.
> z <- getGEO("GPL21061") > zz <- Table(z) > dat$genes <- cbind(dat$genes, zz[match(dat$genes$ProbeName, zz$ID),1:4])
Then you can do all the pre-processing and QC and comparisons, and when you use topTable, you will get all the annotations. Prior to doing topTable you might want to subset to just the columns of interest in the genes list item, as things like the Row or Col, etc are not usually of interest.