2015-05-21 10 views
6

Ich bin ziemlich neu in R und dies ist das erste Mal, dass ich es wage, hier eine Frage zu stellen.R Summe der Zeilen für verschiedene Gruppe von Spalten, die mit ähnlichen Zeichenfolge beginnen

Ich arbeite mit einem Datensatz mit likert Skalen und ich möchte Summe über verschiedene Gruppe von Spalten, die die ersten Zeichenfolgen in ihrem Namen teilen.

Unten habe ich einen Datenrahmen von nur 2 Zeilen erstellt, um den Ansatz zu illustrieren, den ich verfolgt habe, obwohl ich gerne Feedback darüber bekommen würde, wie ich einen effizienteren Weg dazu schreiben kann.

df <- as.data.frame(rbind(rep(sample(1:5),4),rep(sample(1:5),4))) 

var.names <- c("emp_1","emp_2","emp_3","emp_4","sat_1","sat_2" 
      ,"sat_3","res_1","res_2","res_3","res_4","com_1", 
      "com_2","com_3","com_4","com_5","cap_1","cap_2", 
      "cap_3","cap_4") 

names(df) <- var.names 

Also, was ich tat, war die grep-Funktion zu verwenden, um der Lage sein, die Zeilen der angegebenen Variablen zu summieren, die mit bestimmten Zeichenfolgen und speichern sie in einer neuen Variablen gestartet. Aber ich muss für jede Variable eine neue Codezeile schreiben.

df$emp_t <- rowSums(df[, grep("\\bemp.", names(df))]) 
df$sat_t <- rowSums(df[, grep("\\bsat.", names(df))]) 
df$res_t <- rowSums(df[, grep("\\bres.", names(df))]) 
df$com_t <- rowSums(df[, grep("\\bcom.", names(df))]) 
df$cap_t <- rowSums(df[, grep("\\bcap.", names(df))]) 

Aber es gibt viel mehr Variablen im Datensatz, und ich möchte wissen, ob es einen Weg gibt, diese von Code mit nur einer Zeile zu tun. Zum Beispiel eine Möglichkeit, die Variablen, die mit den gleichen Strings beginnen, zu gruppieren und dann die Zeilenfunktion anzuwenden.

Vielen Dank im Voraus!

+0

Nun, wenn das eine Operation ist, die Sie oft tun müssen, klingt es wie Ihre Daten in der falschen Form sind. Es wäre einfacher, mit Daten im "langen" Format als mit dem "Weit" -Format zu arbeiten, das Sie derzeit haben. Es gibt viele andere Fragen zum Umformen, wenn das etwas ist, das du machen willst. – MrFlick

Antwort

3

Eine mögliche Lösung ist df umzusetzen und berechnen Summen für die richtigen Spalten Basis R mit rowsum Funktion (mit set.seed(123))

cbind(df, t(rowsum(t(df), sub("_.*", "_t", names(df))))) 
# emp_1 emp_2 emp_3 emp_4 sat_1 sat_2 sat_3 res_1 res_2 res_3 res_4 com_1 com_2 com_3 com_4 com_5 cap_1 cap_2 cap_3 cap_4 cap_t 
# 1  2  4  5  3  1  2  4  5  3  1  2  4  5  3  1  2  4  5  3  1 13 
# 2  1  3  4  2  5  1  3  4  2  5  1  3  4  2  5  1  3  4  2  5 14 
# com_t emp_t res_t sat_t 
# 1 15 14 11  7 
# 2 15 10 12  9 
+0

ooohh, so nah ... Ich denke, ich mag deine besser (+1) – BrodieG

+0

@BrodieG weiß nicht, ich benutze 't' zweimal hier, also nicht sicher, wie es skalieren wird. (+1) auch für dich :). Schöne Idee, mit '_t' anstatt nur' '' 'btw zu ersetzen. –

+0

Vielen Dank für die Antworten. Bis jetzt wusste ich nicht, was reguläre Ausdrücke waren, aber da ich nicht verstand, warum der "_. * $" Teil funktionierte, musste ich etwas lesen und fand heraus, dass $ hier nicht notwendig ist, 'cbind (df, t (Zeilensumme (t (df), sub ("_.* "," _t ", Namen (df)))))' funktioniert gut. – csmontt

2

mit MrFlick zustimmen, dass Sie möchten, können Sie Ihre Daten im langen Format setzen (siehe reshape2, tidyr), aber Ihre Frage zu beantworten:

cbind(
    df, 
    sapply(split.default(df, sub("_.*$", "_t", names(df))), rowSums) 
) 

den Trick Will

1

Sie werden auf lange Sicht besser dran sein, wenn Sie Ihre Daten in tidy format setzen. Das Problem besteht darin, dass die Daten eher breit als lang sind. Und die Variablennamen, z. B. emp_1, sind tatsächlich zwei getrennte Datenelemente: die Klasse der Person und die ID-Nummer der Person (oder etwas Ähnliches). Hier ist eine Lösung für Ihr Problem mit dplyr und tidyr.

library(dplyr) 
library(tidyr) 
df %>% 
    gather(key, value) %>% 
    extract(key, c("class", "id"), "([[:alnum:]]+)_([[:alnum:]]+)") %>% 
    group_by(class) %>% 
    summarize(class_sum = sum(value)) 

Zunächst wandeln wir den Datenrahmen mit gather() zu langen Format von breit. Dann teilen wir die Werte emp_1 in separate Spalten class und id mit extract(). Schließlich gruppieren wir nach der Klasse und summieren die Werte in jeder Klasse. Ergebnis:

Source: local data frame [5 x 2] 

    class class_sum 
1 cap  26 
2 com  30 
3 emp  23 
4 res  22 
5 sat  19 
+0

funktionieren Sie sollen hier zwei Werte pro Klasse bekommen. Auch, wie es verbindet sich wieder mit den ursprünglichen Daten? –

+0

Ich sehe, wie die ursprüngliche Frage bekam zwei Antworten (dh eine für jede Zeile. Aber es scheint wie der Punkt ist dann, um sie zusammenzufassen? Wenn nicht, dann gibt es eine versteckte Variable hier. Im ursprünglichen df müsste es eine andere Spalte geben, die angibt, was jede Zeile identifiziert. Diese Spalte würde im Aufruf von 'group_by()' enthalten sein. Das Zurückversetzen zu den ursprünglichen Daten ist einfacher. Man könnte 'mutate()' in verwenden "Zusammenfassen", um eine neue Spalte mit diesen Daten hinzuzufügen. Oder man könnte 'left_join()' diesen neuen Datenrahmen zurück in den aufgeräumten Datenrahmen bringen. –