2017-06-24 2 views
1

J'ai une trame de données comme suit:trame de données de Split dans une liste des sous-ensembles de colonnes dans R

> set.seed(123) 
> dat <- data.frame(samples = c("a.1","a.2","a.3","b.1","b.2","b.3"), ID = c(rep("A",3),rep("B",3)) 
> dat 
    samples ID 
1  a.1 A 
2  a.2 A 
3  a.3 A 
4  b.1 B 
5  b.2 B 
6  b.3 B 
> practice.data <- data.frame(a.1 = round(runif(5)), a.2=round(runif(5)), 
    a.3=round(runif(5)),b.1=round(runif(5)),b.2=round(runif(5)),b.3=round(runif(5))) 

> practice.data 
    a.1 a.2 a.3 b.1 b.2 b.3 
1 0 0 1 1 1 1 
2 1 1 0 0 1 1 
3 0 1 1 0 1 1 
4 1 1 1 0 1 0 
5 1 0 0 1 1 0 

Dans l'exemple ci-dessus, je voudrais savoir comment obtenir les trois premières colonnes en objet séparé des trois dernières colonnes (c.-à-d. séparé par ID en dat). Après practice.data est placé dans des listes, je prévois d'utiliser une fonction lapply pour additionner les lignes pour chaque objet de la liste, en retournant un vecteur pour chaque ID. J'ai essayé ceci avec une boucle for-up, mais c'était assez inefficace et j'ai eu trop de problèmes, donc il semble que l'utilisation de listes et l'application peuvent être meilleures, si je peux comprendre comment le faire.

La sortie en fin de compte désiré serait quelque chose comme ceci:

A B 
1 3 
2 2 
2 2 
3 1 
1 2 

Répondre

2
# map column names to the ID 
g <- dat$ID[match(names(practice.data), dat$samples)] 
g 

#[1] A A A B B B 
#Levels: A B 

# split the practice data into smaller data frames based on the map and call rowSums 
as.data.frame(lapply(split.default(practice.data, g), rowSums)) 

# A B 
#1 1 3 
#2 2 2 
#3 2 2 
#4 3 1 
#5 1 2 
0

Voici une option melt/dcast

library(data.table) 
dcast(melt(setDT(practice.data, keep.rownames = TRUE), id.var = 'rn', 
    variable.name = 'samples')[, sum(value), .(rn, samples) 
    ][dat, on = .(samples)], rn~ID, value.var = 'V1', sum)[, rn := NULL][] 
# A B 
#1: 1 3 
#2: 2 2 
#3: 2 2 
#4: 3 1 
#5: 1 2