2014-11-17 11 views
5

Mam ramkę danych, która jest wynikiem innego polecenia. Ta ramka danych ma tylko jeden wiersz z około 40000 wpisów. Mój problem polega na tym, że 3 kolumny to jeden połączony zestaw danych. Dlatego chcę podzielić wiersz po każdej trzeciej kolumnie i przetransportować go jako nowy wiersz. Przykład:Podziel jeden wiersz po każdej trzeciej kolumnie i przenieś te 3 kolumny jako nowy wiersz w r

utworzyć ramkę danych testowych:

df=as.data.frame(matrix(seq(1:12), ncol=12, nrow=1)) 

Teraz mam ramki danych, który wygląda tak.

V1 V2 V3 V4 V5 V6 V7 V8 V9 V10 V11 V12 
1 2 3 4 5 6 7 8 9 10 11 12 

Ale muszę to tak:

V1 V2 V3 
1 2 3 
4 5 6 
7 8 9 
10 11 12 

Jak mogę sobie z tego sprawy?

+1

brzmi dla mnie jak należy naprawić komendę, która stworzyła ten problem! Czy możesz wyjaśnić, jak skończyłeś z super szeroką ramką danych na początek? – A5C1D2H2I1M1N2O1R2T1

Odpowiedz

4

Spróbuj

as.data.frame(matrix(unlist(df, use.names=FALSE),ncol=3, byrow=TRUE)) 
# V1 V2 V3 
#1 1 2 3 
#2 4 5 6 
#3 7 8 9 
#4 10 11 12 

Albo można bezpośrednio wykorzystać matrix na df

as.data.frame(matrix(df, ncol=3, byrow=TRUE)) 
+0

Nie jestem pewien jaka była dodatkowa wartość trzeciej opcji (lub pierwszej) :) –

+0

@David Arenburg Trzecia opcja powinna być oczywiście powolna, ponieważ korzystamy z 't'. Opublikowalem pierwszą opcję, a następnie zdałem sobie sprawę, że można to zrobić bez użycia 'unlist'. – akrun

2

można również spróbować użyć dim<- (tylko dla wiedzy ogólnej)

as.data.frame(t(`dim<-`(unlist(df), c(3, 4)))) 
# V1 V2 V3 
# 1 1 2 3 
# 2 4 5 6 
# 3 7 8 9 
# 4 10 11 12 
1

ta okazała się szybciej niż się spodziewałem (choć stil Nie jestem tak szybki, jak oczywiste podejście, które przyjął @akrun), więc opublikuję to (jak David) "tylko dla ogólnej wiedzy". (Plus. "Data.table" wszystkie rzeczy) :-)

Tworzenie data.table z trzema kolumnami:

  1. niepublicznego wartości swojej jednym rzędzie.
  2. Zmienna grupująca do wskazania, do którego wiersza ma zostać przypisana wartość w końcowym wyjściu.
  3. Zmienna grupująca do wskazania, do której kolumny ma zostać przypisana wartość w końcowym wyjściu.

Po uzyskaniu tego możesz użyć numeru dcast.data.table, aby uzyskać wynik, o którym wspomniałeś (plus kolumna bonusowa).

uzyskać wskazanie ilości 2 powyżej, można łatwo określić funkcję jak następuje, aby proces tworzenia grupy proste:

groupMaker <- function(vecLen, perGroup) { 
    (0:(vecLen-1) %/% perGroup) + 1 
} 

następnie można wykorzystać je w następujący sposób:

dcast.data.table(
    data.table(value = unlist(df, use.names = FALSE), 
      row = groupMaker(ncol(df), 3), 
      col = 1:3), 
    row ~ col) 
# row 1 2 3 
# 1: 1 1 2 3 
# 2: 2 4 5 6 
# 3: 3 7 8 9 
# 4: 4 10 11 12 

Teraz wspominasz, że masz do czynienia z kolumną o jednym wierszu ~ 40K, data.frame (Założę się, że ma ona 39 99 kolumn, ponieważ jest ładnie podzielna przez 3, a ja nie chcę o inne odpowiedzi).

Mając to na uwadze, oto kilka (bezużytecznych) testów porównawczych (bezużyteczne, ponieważ mówimy tutaj naprawdę milisekundy).

set.seed(1) 
S <- sample(20, 39999, TRUE) 
S <- data.frame(t(S)) 

funAM <- function(indf) { 
    dcast.data.table(
    data.table(value = unlist(indf, use.names = FALSE), 
       row = groupMaker(ncol(indf), 3), 
       col = 1:3), 
    row ~ col) 
} 

funDA <- function(indf) { 
    as.data.frame(t(`dim<-`(unlist(indf), c(3, ncol(indf)/3)))) 
} 

funAK <- function(indf) as.data.frame(matrix(indf, ncol=3, byrow=TRUE)) 

library(microbenchmark) 
microbenchmark(funAM(S), funDA(S), funAK(S)) 
# Unit: milliseconds 
#  expr  min  lq  mean median  uq  max neval 
# funAM(S) 18.487001 18.813297 22.105766 18.999891 19.455812 50.25876 100 
# funDA(S) 37.187177 37.450893 40.393893 37.870683 38.869726 94.20128 100 
# funAK(S) 5.018571 5.149758 5.929944 5.271679 5.536449 26.93281 100 

Gdzie ten potęga być użyteczne byłoby w przypadku, gdy liczba żądanych kolumn a liczba kolumn wejściowych nie są ładnie podzielna przez siebie.

Spróbuj na przykład następujące dane przykładowe:

set.seed(1) 
S2 <- sample(20, 40000, TRUE) 
S2 <- data.frame(t(S)) 

Z tych danych próbki:

  • funAM dałby ci warning ale właściwie daje dwie ostatnie kolumny ostatnim rzędzie jako NA.
  • funAK dałoby ci warning, ale prawdopodobnie (prawdopodobnie) nieprawidłowo zawróci wartości z ostatniego wiersza.
  • funDA po prostu da ci error.

Nadal uważam, że należy po prostu rozwiązać ten problem u źródła chociaż :-)

Powiązane problemy