2011-03-08 12 views
54

Właśnie zaczynam od R i napotkałem dziwne zachowanie: podczas wstawiania pierwszego wiersza w pustej ramce danych, oryginalne nazwy kolumn zostaną utracone.R: utrata nazw kolumn podczas dodawania wierszy do pustej ramki danych

przykład:

a<-data.frame(one = numeric(0), two = numeric(0)) 
a 
#[1] one two 
#<0 rows> (or 0-length row.names) 
names(a) 
#[1] "one" "two" 
a<-rbind(a, c(5,6)) 
a 
# X5 X6 
#1 5 6 
names(a) 
#[1] "X5" "X6" 

Jak widać, nazwy kolumn jeden i dwa zostały zastąpione przez X5 i X6.

Czy ktoś mógłby mi powiedzieć, dlaczego tak się dzieje i czy jest to właściwy sposób bez utraty nazw kolumn?

Rozwiązaniem z zakresu strzelby byłoby zapisanie nazw w pomocniczym wektorze, a następnie dodanie ich z powrotem po zakończeniu pracy nad ramką danych.

Dzięki

Kontekst:

stworzyłem funkcję która gromadzi pewne dane i dodaje je jako nowy wiersz do ramki danych otrzymanych jako parametr. Tworzę ramkę danych, iteruję przez moje źródła danych, przekazując dane.frame do każdego wywołania funkcji w celu uzupełnienia ich wynikami.

Odpowiedz

28

W rbind strony pomocy określa, że:

Dla 'cbind' ('rbind'), wektory zerowej długości (w tym 'NULL') są ignorowane chyba że wynik będzie mieć zero wierszy (kolumny) dla zgodności S. (macierze Zero stopniu nie występują w S3 i nie są ignorowane w R.)

Więc w rzeczywistości a jest ignorowany w instrukcji rbind. Nie całkowicie ignorowane, jak się wydaje, bo jak to jest ramka danych funkcja rbind nazywa się rbind.data.frame:

rbind.data.frame(c(5,6)) 
# X5 X6 
#1 5 6 

może jeden sposób, aby wstawić wiersz może być:

a[nrow(a)+1,] <- c(5,6) 
a 
# one two 
#1 5 6 

Ale nie może być lepszy sposób na zrobienie tego w zależności od kodu.

8

Obejście byłoby:

a <- rbind(a, data.frame(one = 5, two = 6)) 

?rbind stwierdza, że ​​łączenie przedmiotów wymaga dopasowania nazwy:

Następnie wykonuje klas kolumn z pierwszej ramki danych oraz meczów kolumn, nazwa (zamiast według pozycji)

+0

Myślę, że w twoim kodzie '' rbind' A' wewnątrz jest ignorowany, więc jest to w istocie równoważne 'a <- data.frame (jeden = 5, two = 6) '. Ale mogę się mylić. – juba

+0

+1 Zwykle używam tego podejścia - zauważ, że możesz po prostu zainicjować "a" na pustym wektorze: 'a <- c()'. –

+0

@juba, może tak być, ponieważ data.frame 'a' jest puste. –

7

FWIW alternatywny projekt może mieć swoje funkcje wektorów budowlanych na dwóch kolumnach, zamiast rbinding do ramki danych:

ones <- c() 
twos <- c() 

zmodyfikować wektory w swoich funkcjach:

ones <- append(ones, 5) 
twos <- append(twos, 6) 

Repeat w razie potrzeby, a następnie utwórz dane.frame za jednym razem:

a <- data.frame(one=ones, two=twos) 
+1

niesamowicie pomocny. być może nie tak zwięźle, ale przepływ danych jest trochę mniej czarny. – Andrew

+0

Rzeczywiście ładna odpowiedź. Ale wydaje się bardzo "nie R". Podczas konstruowania data.frame musisz najpierw * przelotować * nad całą zawartością, podczas gdy operatory wiersza są końmi roboczymi R. Może używając odpowiedzi @juby, ale ustawić nazwy na końcu: 'colnames (a) <- c (" jeden "," dwa ")'? – user989762

+0

Problem z tym podejściem polega na tym, że często nazwy kolumn wymagają rozszerzenia ramki danych. Dlaczego tak proste rzeczy są tak skomplikowane w r ...? – TMOTTM

7

było prawie surrende zadzwoń do tego problemu.

1) utworzyć ramkę danych z stringsAsFactor zestaw do FALSE lub uruchomić prosto w następnym numerze

2) nie używać rbind - nie wiem dlaczego na ziemi jest brudząc się nazwy kolumn. po prostu zrobić to w ten sposób:

df[nrow(df)+1,] <- c("d","gsgsgd",4)

df <- data.frame(a = character(0), b=character(0), c=numeric(0)) 

df[nrow(df)+1,] <- c("d","gsgsgd",4) 

#Warnmeldungen: 
#1: In `[<-.factor`(`*tmp*`, iseq, value = "d") : 
# invalid factor level, NAs generated 
#2: In `[<-.factor`(`*tmp*`, iseq, value = "gsgsgd") : 
# invalid factor level, NAs generated 

df <- data.frame(a = character(0), b=character(0), c=numeric(0), stringsAsFactors=F) 

df[nrow(df)+1,] <- c("d","gsgsgd",4) 

df 
# a  b c 
#1 d gsgsgd 4 
1

Można to zrobić:

dać jeden wiersz do początkowego ramki danych

df=data.frame(matrix(nrow=1,ncol=length(newrow)) 

dodać nowy wiersz i wyjąć NAS

newdf=na.omit(rbind(newrow,df)) 

, ale uważaj, że twój newrow nie ma NA, albo zostanie wymazany.

Cheers Agus

-1

Zamiast budowy data.frame z numeric(0) używam as.numeric(0).

a<-data.frame(one=as.numeric(0), two=as.numeric(0)) 

Stwarza to dodatkowy wstępny wiersz

a 
# one two 
#1 0 0 

Bind dodatkowe rzędy

a<-rbind(a,c(5,6)) 
a 
# one two 
#1 0 0 
#2 5 6 

Następnie za pomocą ujemnego indeksowanie aby usunąć pierwsze (podrobiony) wierszu

a<-a[-1,] 
a 

# one two 
#2 5 6 

Uwaga: to psuje się th e indeks (daleko po lewej). Nie wymyśliłem, jak temu zapobiec (komukolwiek innemu?), Ale przez większość czasu to chyba nie ma znaczenia.

+0

Najczęściej to robi. – TMOTTM

0

Jednym ze sposobów, aby to zrobić w sposób ogólny i przy najmniejszym ponownym wpisywaniu nazw kolumn jest następujący. Metoda ta nie wymaga hacking Na lub 0.

rs <- data.frame(i=numeric(), square=numeric(), cube=numeric()) 
for (i in 1:4) { 
    calc <- c(i, i^2, i^3) 
    # append calc to rs 
    names(calc) <- names(rs) 
    rs <- rbind(rs, as.list(calc)) 
} 

RS będzie miał poprawne nazwy

> rs 
    i square cube 
1 1  1 1 
2 2  4 8 
3 3  9 27 
4 4  16 64 
> 

Innym sposobem, aby to zrobić w bardziej elegancki jest użycie danych.tabela:

> df <- data.frame(a=numeric(0), b=numeric(0)) 
> rbind(df, list(1,2)) # column names are messed up 
> X1 X2 
> 1 1 2 

> df <- data.table(a=numeric(0), b=numeric(0)) 
> rbind(df, list(1,2)) # column names are preserved 
    a b 
1: 1 2 

Należy zauważyć, że data.table jest również data.frame.

> class(df) 
"data.table" "data.frame" 
0

użyć następujące rozwiązanie dodać wiersz pustej ramce danych:

d_dataset <- 
    data.frame(
    variable = character(), 
    before = numeric(), 
    after = numeric(), 
    stringsAsFactors = FALSE) 

d_dataset <- 
    rbind(
    d_dataset, 
     data.frame(
     variable = "test", 
     before = 9, 
     after = 12, 
     stringsAsFactors = FALSE)) 

print(d_dataset) 

variable before after 
1  test  9 12 

HTH.

poważaniem

Georg

Powiązane problemy