2017-06-05 6 views
1

Variablen werden fälschlicherweise in mehrere Spalten eingegeben zB: "aaa_1", "aaa_2" und "aaa_3", oder "ccc_1," ccc_2 ", und" ccc_3 ") einzelne neue Spalten (zB „aaa“ oder „ccc“). sind einige Variablen, die gegenwärtig in einer einzigen Spalte obwohl („hhh_1“), aber mehr Spalten hinzugefügt werden können (hhh_2 usw.).Mehrere Spalten verarbeiten und dynamisch neue Spalten benennen

Das ist, was ich habe :

aaa_1 <- c(43, 23, 65, NA, 45) 
aaa_2 <- c(NA, NA, NA, NA, NA)  
aaa_3 <- c(NA, NA, 92, NA, 82) 
ccc_1 <- c("fra", NA, "spa", NA, NA) 
ccc_2 <- c(NA, NA, NA, "wez", NA) 
ccc_3 <- c(NA, "ija", NA, "fda", NA)  
ccc_4 <- c(NA, NA, NA, NA, NA) 
hhh_1 <- c(183, NA, 198, NA, 182)  
dataf1 <- data.frame(aaa_1,aaa_2,aaa_3,ccc_1,ccc_2, ccc_3,ccc_4,hhh_1) 

Dies ist, was ich will:

aaa <- c(43, 23, NA, NA, NA) 
ccc <- c("fra", "ija", "spa", NA, NA) 
hhh <- c(183, NA, 198, NA, 182) 
dataf2 <- data.frame(aaa,ccc,hhh) 

Allgemeine Lösung benötigt ~ 100 Variablen (zB "aaa", "hhh", "ccc", "ttt", "eee", "hhh" usw.).

Danke!

Antwort

0

Dies ist eine Basislösung, d. H. Keine Pakete.

Definieren Sie zunächst get_only, die bei Angabe einer Liste in ein data.frame konvertiert wird und auf jede Zeile get_only anwendet. Wenn ein Vektor gegeben wird, gibt er die einzelne Nicht-NA in ihm oder NA zurück, wenn es nicht nur eine gibt.

Definieren Sie root als die Spaltennamen ohne die Suffixe.

Konvertieren Sie den Datenrahmen in eine Spaltenliste, gruppieren Sie sie nach root und wenden Sie get_only auf jede dieser Gruppen an.

Schließlich konvertieren Sie die resultierende Liste in einen Datenrahmen.

get_only <- function(x) UseMethod("get_only") 
get_only.list <- function(x) apply(data.frame(x), 1, get_only) 
get_only.default <- function(x) if (sum(!is.na(x)) == 1) na.omit(x) else NA 

root <- sub("_.*", "", names(dataf1)) 
as.data.frame(lapply(split(as.list(dataf1), root), FUN = get_only)) 

geben:

age country hight 
1 43  fra 183 
2 23  ija NA 
3 NA  spa 198 
4 NA <NA> NA 
5 NA <NA> 182 
+0

Vielen Dank für die Erklärung so sorgfältig! – LLL

0

können wir versuchen, mit splitstackshape

library(splitstackshape) 
nm1 <- sub("_\\d+", "", names(dataf1)) 
tbl <- table(nm1) > 1 
merged.stack(dataf1, var.stubs = names(tbl)[tbl], sep="_") 
0

Ich bin dein Beispiel stimmt nicht sicher. Zum Beispiel in der dritten Zeile haben Sie Werte für age_1 und age_3, dann in der gewünschten Ausgabe NA für diese Zeile.

Wenn ich verstanden habe, was Sie tun möchten, wird es viel einfacher, wenn Sie Spalten in Zeilen transponieren, sie korrigieren und dann wieder zurück transponieren. Versuchen Sie dies als Ausgangspunkt, indem Sie 'didyverse' von dplyr und tidyr verwenden.

library(tidyverse) 
library(stringr) 

age_1 <- c(43, 23, 65, NA, 45) 
age_2 <- c(NA, NA, NA, NA, NA) 
age_3 <- c(NA, NA, 92, NA, 82) 
country_1 <- c("fra", NA, "spa", NA, NA) 
country_2 <- c(NA, NA, NA, "wez", NA) 
country_3 <- c(NA, "ija", NA, "fda", NA) 
country_4 <- c(NA, NA, NA, NA, NA) 
hight_1 <- c(183, NA, 198, NA, 182) 
dataf1 <- data.frame(age_1,age_2,age_3,country_1,country_2, country_3,country_4,hight_1) 

data <- dataf1 %>% 
    mutate(row_num = row_number()) %>% #create a row number to track values 
    gather(key, value, -row_num) %>% #flatten your data 
    drop_na() %>% #drop na rows 
    mutate(key = str_replace(key, "_.", "")) %>% #remove the '_x' part of names 
    group_by(row_num) %>% 
    top_n(1) %>% 
    spread(key, value) #pivot back to columns 

Für Ihr Beispiel müssen Sie die group_by() und top_n() Linien zu machen, laufen, weil Sie mehrere Werte in der gleichen Zeile haben. Wenn Sie nur einen Wert haben (wie ich denke, sollten Sie?), Dann können Sie diese zwei Zeilen entfernen. Es wird besser ohne sie, denn dann wird es nicht laufen, wenn Ihre Daten falsch sind.

Bearbeiten Sie den folgenden Kommentar unten. Dies macht doppelte Einträge zu NA.

data <- dataf1 %>% 
    mutate(row_num = row_number()) %>% #create a row number to track values 
    gather(key, value, -row_num) %>% #flatten your data 
    drop_na() %>% #drop na rows 
    mutate(key = str_replace(key, "_.", "")) %>% #remove the '_x' part of names 
    group_by(row_num, key) %>% 
    mutate(count = n()) %>% #count how many entries for each row/key combo 
    mutate(value = ifelse(count > 1, NA, value)) %>% #set NA for rows with duplicates 
    drop_na() %>% 
    spread(key, value) %>% #pivot back to columns 
    select(-count) #drop the `count` variable 
+0

ich sicherstellen möchten, dass, wenn eine bestimmte Person das Alter hat, da beide 65 (age_1) und 92 (age_3) eingegeben wurde, wird der Ausgang NA ist (wie ich kann‘ t sicher sein, welches der Jahre richtig ist, möchte ich diese Beobachtung/Zeile unterstellen können). Vielen Dank! – LLL

+0

Bearbeitete meine Antwort oben. Sie können Einträge zählen und alle Zeilen mit Duplikaten entfernen – NeilC