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:
- niepublicznego wartości swojej jednym rzędzie.
- Zmienna grupująca do wskazania, do którego wiersza ma zostać przypisana wartość w końcowym wyjściu.
- 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ż :-)
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