2017-12-27 27 views
1

ich einen Datenrahmen ähnlich wie diese Probe haben:Optimieren: Wertersatz in Datenrahmen Wiith mehrere Bedingungen

df <- structure(list(Ball = structure(c(5L, 3L, 2L, 4L, 1L, 3L), .Label = c("blue", "blue is my favourite", "red", "red ", "red ball"), class = "factor"), size = c(1.2, 2, 3, 10, 12, 100)), .Names = c("Ball", "size"), class = "data.frame", row.names = c(NA, -6L)) 

Basierend auf den Informationen in den beiden Spalten ich die Einzelteile durch Größe und Farbe klassifizieren möchten. Die Ausgabe sollte wie folgt aussehen:

structure(list(Ball = structure(c(5L, 3L, 2L, 4L, 1L, 3L), .Label = c("blue", "blue is my favourite", "red", "red ", "red ball"), class = "factor"), size = c(1.2, 2, 3, 10, 12, 100), Class = c("small red ball", "small red ball", "small blue ball", "medium red ball", "medium blue ball", "big red ball")), row.names = c(NA, -6L), .Names = c("Ball", "size", "Class"), class = "data.frame") 

I-Code ausgeführt haben, aber es ist sehr lang und chaotisch, und ich bin sicher, es ist eine nette Art und Weise meine gewünschte Ausgabe zu erhalten.

Also was habe ich getan?

Ich begann mit den Elementen der ersten Klasse auswählen und benennen Sie die ausgewählten df$Class Werte:

df["Class"] <- NA #add new column 

df[grepl("red", df$Ball) & df$size <10, ]$Class <- "small red ball" 

und weil meine Grepl-Auswahl manchmal leer ist, habe ich einen if (length() > 0) Zustand:

if (length(df[grepl("red", df$Ball) & df$size <10, ]$Class) > 0) {df[grepl("red", df$Ball) & df$size <10, ]$Class <- "small red ball"} 

und schließlich ich kombiniert alle meine Auswahl in einer Schleife

df["Class"] <- NA #add new column 
z <- c("red", "blue") 

for (i in z){ 
    if (length(df[grepl(i, df$Ball) & df$size <10, ]$Class) > 0) {df[grepl(i, df$Ball) & df$size <10, ]$Class <- paste("small", i, "ball", sep=" ")} 
    if (length(df[grepl(i, df$Ball) & df$size >=10 & df$size <100, ]$Class) > 0) {df[grepl(i, df$Ball) & df$size >=10 & df$size <100, ]$Class <- paste("medium", i, "ball", sep=" ")} 
    if (length(df[grepl(i, df$Ball) & df$size >=100, ]$Class) > 0) {df[grepl(i, df$Ball) & df$size >=100, ]$Class <- paste("big", i, "ball", sep=" ")} 
} 

Es funktioniert für zwei Farben und drei Größenkategorien, aber mein ursprünglicher Datenrahmen ist viel größer. Deshalb (und weil es so chaotisch aussieht), meine Frage: Wie kann ich meinen Code vereinfachen?

Antwort

2

Wir können cut verwenden, um die Gruppierung zu erstellen auf der Grundlage der ‚Größe‘ und paste es mit den extrahierten Werten von ‚Ball‘ mit str_extract

library(stringr) 
df$Class <- with(df, paste(as.character(cut(size, breaks = c(1, 9, 99, Inf), 
    labels = c('small', 'medium', 'big'))), str_extract(Ball, 'red|blue'), 'ball')) 
df$Class 
#[1] "small red ball" "small red ball" "small blue ball" 
#[4] "medium red ball" "medium blue ball" "big red ball"  
+1

Ich sehe nicht die Essenz des 'saithr'-Pakets. Ich denke, Basis r funktioniert fin: 'einfügen (as.character (cut (df $ size, c (1,10,100, Inf), c (" klein "," mittel "," groß "))), sub (" [^ (rot | blau)]. * "," ", df $ Ball), 'Ball')' – Onyambu

+0

@Onyambu Sicher funktioniert das 'sub', aber wenn es keine Übereinstimmungen gibt, dann könnte es die ganze Zeichenfolge wo zurückgeben als 'str_extract' gibt NA zurück. Eine Umgehungslösung wäre "regexpr/regmatches" – akrun

+0

Die Unterbrechungen sollten "c (1, 9, 99, Inf)" für "klein: x <10", "mittel 10 <= x <100", "groß: x>" sein = 100', oder? – Iris

1

Scheint wie ein großer Fall die dplyr und stringr zu verwenden Pakete:

library(stringr) 
library(dplyr) 

df <- structure(list(Ball = structure(c(5L, 3L, 2L, 4L, 1L, 3L), .Label = c("blue", "blue is my favourite", "red", "red ", "red ball"), class = "factor"), size = c(1.2, 2, 3, 10, 12, 100)), .Names = c("Ball", "size"), class = "data.frame", row.names = c(NA, -6L)) 


df %>% 
    mutate(
    color = str_extract(`Ball`, "(red)|(blue)"), 
    size_category = case_when(
     size < 10 ~ "small", 
     size >= 10 & size < 100 ~ "medium", 
     size >= 100 ~ "large" 
    ), 
    category = str_c(size_category, color, "ball", sep = " ") 
) 
2

Diese Antwort auf @ akrun sind sehr ähnlich ist, aber Sie können mehr Farben enthalten (hier bin ich bin mit der colors() Palette, aber y Sie können auch andere benutzen. Ich änderte auch leicht die Argumente für die Funktion.

size<- cut(df$size, c(0, 10, 100, Inf), labels = c("small", "medium", "big"), right=F) 
colors<- str_extract(df$Ball, paste(colors(), collapse="|")) 
df$Class<- paste(size, colors, "ball", sep = " ") 

> df 
        Ball size   Class 
1    red ball 1.2 small red ball 
2     red 2.0 small red ball 
3 blue is my favourite 3.0 small blue ball 
4     red 10.0 medium red ball 
5     blue 12.0 medium blue ball 
6     red 100.0  big red ball 

Auch machen es ein bisschen mehr der Regel können Sie für Großbuchstaben ermöglichen durch den Einsatz:

colors<- str_extract(df$Ball, regex(paste(colors(), collapse="|"), ignore_case=T)) 

Also, wenn df$Ball[1] = "Red ball", mit der Linie über Sie erhalten:

colors 
#[1] "Red" "red" "blue" "red" "blue" "red" 
df$Class<- paste(size, tolower(colors), "ball", sep = " ") 
df$Class 
#[1] "small red ball" "small red ball" "small blue ball" "medium red ball" "medium blue ball" 
#[6] "big red ball"