2017-05-15 5 views
0

Nach einem (sehr Erschrecken) dplyr Pipeline Ich habe mit einem Datensatz wie folgt ende:Divide (und Name) eine Gruppe von Spalten von einer anderen Gruppe in dplyr

year A B  C [....] Z count.A count.B  count.C [....] count.Z 
1999 10 20 10 ... 6  3   5   67 ...  6 
2000 3 5  5 ... 7  5   2   5 ...  5 

Einige Daten Beispiel zu reproduzieren:

df <- data.frame(year = c(1999, 2000), 
       A = c(10, 20), 
       B = c(3, 6), 
       C = c(1, 2), 
       count.A = c(1, 2), 
       count.B = c(8, 9), 
       count.C = c(5, 7)) 

Was ich wirklich brauchen, ist jede Spalte mit ihrem „count“ gegen~~POS=TRUNC zu kombinieren, dh

weight.A = A/count.A, 
weight.B = B/count.B 

ich habe zu tun, dass programmatisch, da ich Hunderte von Spalten habe. Gibt es eine Möglichkeit, dies in einer dplyr-Pipeline zu tun?

+0

Was hat das mit 'rowSums' zu tun? Sie sollten den Titel wahrscheinlich bearbeiten. – alistaire

Antwort

3

speichern Sie keine Variablen in Spaltennamen. Wenn Sie Ihre Daten neu zu gestalten, um es ordentlich zu machen, ist die Berechnung sehr einfach:

library(tidyverse) 

df %>% gather(var, val, -year) %>% # reshape to long 
    separate(var, c('var', 'letter'), fill = 'left') %>% # extract var from former col names 
    mutate(var = coalesce(var, 'value')) %>% # add name for unnamed var 
    spread(var, val) %>% # reshape back to wide 
    mutate(weight = value/count) # now this is very simple 

#> year letter count value  weight 
#> 1 1999  A  1 10 10.0000000 
#> 2 1999  B  8  3 0.3750000 
#> 3 1999  C  5  1 0.2000000 
#> 4 2000  A  2 20 10.0000000 
#> 5 2000  B  9  6 0.6666667 
#> 6 2000  C  7  2 0.2857143 
+0

liebe diesen sauberen Ansatz! funktioniert perfekt! –

1

Angenommen, Sie können programmatisch einen Vektor aller Spaltennamen erstellen, ist hier, wie ich für Ihr Beispiel tun würde über

for (c.name in c("A", "B", "C")) { 
    c.weight <- sprintf("weight.%s", c.name) 
    c.count <- sprintf("count.%s", c.name) 
    df[,c.weight] <- df[,c.name]/df[,c.count] 
} 
2

Wenn Ihre Spalten konsequent benannt sind (und leicht genug, um zu holen) konnte man leicht Dazu ein lapply mit:

cols <- c("A","B","C") 
df[,paste0("weighted.",cols)] <- lapply(cols, function(x) df[,x]/df[, paste0("count.",x)]) 

# year A B C count.A count.B count.C weighted.A weighted.B weighted.C 
#1 1999 10 3 1  1  8  5   10 0.3750000 0.2000000 
#2 2000 20 6 2  2  9  7   10 0.6666667 0.2857143 
1

Unter der Annahme, dass die Spalten in Ordnung sind, können wir data.table verwenden. Geben Sie die Spalten von Interesse in .SDcols und dividieren durch Teilmenge von Spalten von Subset von Data.table mit der anderen Hälfte und zuweisen (:=), um neue Spalten

library(data.table) 
setDT(df)[, paste0("weighted.",names(df)[1:3]) := .SD[,1:3]/.SD[,4:6], .SDcols = A:count.C] 
df 
# year A B C count.A count.B count.C weighted.year weighted.A weighted.B 
#1: 1999 10 3 1  1  8  5   10 0.3750000 0.2000000 
#2: 2000 20 6 2  2  9  7   10 0.6666667 0.2857143 
Verwandte Themen