简体   繁体   中英

Aggregating frequency of column entries into separate columns in R

I have a data frame that looks like:

POP<-c(rep("POP1",6), rep("POP2",6), rep("POP3", 6))
IID<-c(rep("POP1_1", 2), rep("POP1_2",2), rep("POP1_3", 2), rep("POP2_1",2), rep("POP2_2",2), rep("POP2_3",2), rep("POP3_1",2), rep("POP3_2",2),rep("POP3_3",2))
Site1<-c(36, 42, 32, 32, 48, 42, 36, 36, 48, 42, 36, 48, 28, 32, 32, 32, 48, 32)
Site2<-c(10, 8, 10, 16, 16, 10, 10, 10, 16, 10, -9, -9, 16, 8, 10, 10, 8, 8)
dat<-cbind(POP, IID, Site1, Site2)

With many more columns of sites, and many more POP groups. I want to go through by columns and for each different entry in the column I want a new column to contain the frequency of that entry, aggregated over the POP column. -9 denotes missing values. I do not want these to constitute a column, or to contribute to the frequency.

Ultimately, the data above would look like:

dat

POP   Site1_28 Site1_32 Site1_36 Site1_42 Site1_48 Site2_8 Site2_10 Site2_16
POP1  0        0.333    0.167    0.333    0.166    0.167   0.5      0.333   
POP2  0        0        0.5      0.167    0.333    0       0.75     0.25    
POP3  0.167    0.667    0        0        0.167    0.5     0.333    0.167

I'm guessing I'll be looking at lapply() over some use of table() and aggregate(), but I really have no idea where to start.

Thank you!

I think this should do what you want. First, we do some data manipulation to make our call to table work. Then, we iterate over the two columns, performing a prop.table for the sites by each POP value. Finally, we use rbind and cbind to combine the data.

#create data.frame
dat<-data.frame(POP, IID, Site1, Site2,
                stringsAsFactors = FALSE)
#identify columns containing 'Site'
site_col_names <- names(dat)[grep(pattern = 'Site', x = names(dat))]
#for each site column, recode -9 as NA, and then paste
for(i in site_col_names){
  dat[i] <- factor(sapply(dat[i], function(x) 
    ifelse(x == -9, NA, paste0(i,'_',x))))
}
#iterate over columns, calculate prop.table
do.call('cbind',
        lapply(site_col_names, function(n){
          do.call('rbind',
                  by(dat, dat$POP, function(d) prop.table(table(d[n]))))
        }))

      Site1_28  Site1_32  Site1_36  Site1_42  Site1_48  Site2_10  Site2_16   Site2_8
POP1 0.0000000 0.3333333 0.1666667 0.3333333 0.1666667 0.5000000 0.3333333 0.1666667
POP2 0.0000000 0.0000000 0.5000000 0.1666667 0.3333333 0.7500000 0.2500000 0.0000000
POP3 0.1666667 0.6666667 0.0000000 0.0000000 0.1666667 0.3333333 0.1666667 0.5000000

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM