Marcin Bronicki

Marcin Bronicki kierownik, własna

Temat: problem z replikacją danych

Mam dane z bazy takiego typu.
Ilosc_wystapien, wartosc1, wartosc2.
6____________________nie______A
4____________________tak______B

Robię takie agregaty bo danych dużo, eksport pojedynczych rekordów trwał by długo. Ale są obliczenia w R gdzie muszę mieć każdy rekord oddzielnie.
wartosc1, wartosc2
nie__________A
nie__________A
nie__________A
nie__________A
nie__________A
nie__________A
tak__________B
tak__________B
tak__________B
tak__________B

Jak to zrobić? Wiem że pamięć się rozrośnie ale nie mam wyjścia.
Próbowałem wykorzystać 'rep' ale to raczej chyba do wektora, a ja raczej to potrzebuję w data.frame.

Temat: problem z replikacją danych

Tak na szybko:

Rozgrupuj <- function(Zgrupowane) {
wartosci1 <- c()
wartosci2 <- c()

for(i in 1:length(Zgrupowane[,1])) {

w1 <- Zgrupowane[i,3]
w2 <- Zgrupowane[i,2]

ile_powtorek <- Zgrupowane[i,1]

wartosci1 <- c(wartosci1, rep(as.character(w1), ile_powtorek))
wartosci2 <- c(wartosci2, rep(as.character(w2), ile_powtorek))
}
return (Wynik = data.frame(wartosci1 ,wartosci2))
}


Wynik działania:
> a <- c(6, 4)
> b <- c('nie', 'tak')
> c <- c('A', 'B')
> Zgrupowane <- data.frame(Licznosc=a, Wartosc1=b, Wartosc2=c)
> Zgrupowane
Licznosc Wartosc1 Wartosc2
1 6 nie A
2 4 tak B
> Rozgrupuj(Zgrupowane)
wartosci1 wartosci2
1 A nie
2 A nie
3 A nie
4 A nie
5 A nie
6 A nie
7 B tak
8 B tak
9 B tak
10 B tak


Zapewne są wydajniejsze procedury (może reshape?), ale nie mam serca kopać w nielubianej przeze mnie dokumentacji R o 3 nad ranem :)

W każdym razie dla danych wejściowych
x <- c()
y <- c()
z <- c()

for(i in 1:1000) {
x <- c(x, i)
y <- c(y, paste('wartosc1', as.character(i)))
z <- c(z, paste('wartosc2', as.character(i)))
}
Zgrupowane <- data.frame(Licznosc=x, Wartosc1=y, Wartosc2=z)


transformacja trwała 6 sekund na laptopie z Core2Duo 2GHz (aktywny 1 rdzeń).Adrian Olszewski edytował(a) ten post dnia 08.02.10 o godzinie 03:34
Michał Bojanowski

Michał Bojanowski socjolog, analityk

Temat: problem z replikacją danych

Alternatywnie, chyba prościej, a na pewno szybciej.


rozgrupuj2 <- function(dat, vnam="Ilosc_wystapien")
{
vind <- match(vnam, names(dat))
stopifnot(!is.na(vind))
dat[ rep(1:nrow(dat), dat[,vind]) , -vind ]
}


Np na danych Adriana:


> x <- c()
> y <- c()
> z <- c()
> for(i in 1:1000) {
+ x <- c(x, i)
+ y <- c(y, paste('wartosc1', as.character(i)))
+ z <- c(z, paste('wartosc2', as.character(i)))
+ }
> Zgrupowane <- data.frame(Licznosc=x, Wartosc1=y, Wartosc2=z)
> system.time(rozgr2 <- Rozgrupuj(Zgrupowane))
user system elapsed
7.000 0.750 7.749
> system.time(rozgr <- rozgrupuj2(Zgrupowane, "Licznosc"))
user system elapsed
1.180 0.020 1.196


7 razy szybciej...

Wartosci te same, roznice tylko w atrybutach.


identical(rozgr, rozgr2)
[1] FALSE
identical( rozgr[,1], rozgr2[,1] )
[1] TRUE
identical( rozgr[,2], rozgr2[,2] )
[1] TRUE
Michał Bojanowski edytował(a) ten post dnia 08.02.10 o godzinie 12:45

Temat: problem z replikacją danych

W życiu nie nauczę się eRa... <ściana><ściana><ściana>
:)

EDIT:
zajarzyłem :)Adrian Olszewski edytował(a) ten post dnia 08.02.10 o godzinie 12:50
Michał Bojanowski

Michał Bojanowski socjolog, analityk

Temat: problem z replikacją danych

Adrian Olszewski:
W życiu nie nauczę się eRa... <ściana><ściana><ściana>
:)

hehe, nie trzeba desperować, wszystko kwestia praktyki
Marcin Bronicki

Marcin Bronicki kierownik, własna

Temat: problem z replikacją danych

Michał Bojanowski:
Alternatywnie, chyba prościej, a na pewno szybciej.


rozgrupuj2 <- function(dat, vnam="Ilosc_wystapien")[/quote]> {[quote] vind <- match(vnam, names(dat))[/quote]> stopifnot(!is.na(vind))[quote] dat[ rep(1:nrow(dat), dat[,vind]) , -vind ]
}

Jak dla mnie nie za prosto :)
Rozumiem że wywołuję
rozgrupuj2(co,ile)

jak wspominałem mam plik jak dałem na początku.
podaję więc
rozgrupuj2(dane$wartosc1,dane$wartosc2,dane$ilosc)

Ale dostaję
Error: !is.na(vind) is not all TRUE


Co wstawiam nie tak?

Temat: problem z replikacją danych

Funkcja Michała przyjmuje dwa parametry: nazwę ramki i nazwę kolumny w tej ramce, w której znajdują się licz(eb)ności poszczególnych grup.

W pierwszym i drugim kroku sprawdzane jest, czy w ramce jest wspomniana kolumna z licznościami - i jeśli jest, pobierany jest jej indeks (numer). Numer ten zapisywany jest w zmiennej vind (variable index? :) ).

Gdyby zmiennej o zadanej nazwie nie było (np. literówka w nazwie), wyrażenie zwróci "NA" (not available), co wykryje druga linijka i zakończy działanie funkcji.

Jeśli wszystko jest OK, trzecia linijka "czyni" następujące rzeczy:

1. Generuje ciąg liczb od 1 do liczba wierszy w ramce powtórzonych tyle razy, ile wskazują kolejne elementy wektora Zgrupowane[,vind].

Ponieważ każdy wiersz ramki to u Ciebie osobna grupa, więc de facto otrzymujesz indeksy grup, powielone tyle, na ile wskazuje zawartość kolumny z liczebnościami.

> vind   # tutaj zapisany jest indeks kolumny z liczebnościami
[1] 1

> Zgrupowane[,vind]
[1] 6 4

> rep(1:nrow(Zgrupowane), Zgrupowane[,vind])
[1] 1 1 1 1 1 1 2 2 2 2


2. Uzyskanymi "indeksami grup" indeksuje wiersze w ramce, jednocześnie wymuszając ich powielenie (wybierz: "pierwszą grupę, pierwszą grupę, pierwszą grupę..... drugą grupę, drugą grupę..."). Dodatkowo wybiera wszystkie kolumny z pominięciem zbędnej kolumny z liczebnościami.

Reasumując - zakładając, że masz ramkę taką, jak pokazałeś w swoim przykładzie (musi mieć jedną kolumnę z liczebnościami i dowolną liczbę kolumn z danymi):
Ilosc_wystapien, wartosc1, wartosc2.
6____________________nie______A
4____________________tak______B

podajesz właśnie tę ramkę oraz nazwę kolumny "Ilosc_wystapien" jako drugi argument.

> rozgrupuj2(dane, "Ilosc_wystapien")
Adrian Olszewski edytował(a) ten post dnia 08.02.10 o godzinie 15:51
Michał Bojanowski

Michał Bojanowski socjolog, analityk

Temat: problem z replikacją danych

Dzięki Adrian, sam bym lepiej nie napisał :)

Pamiętam, że czytałem kiedyś jakiś post na Rhelp, w którym ktoś mądrze napisał, że umiejętne korzystanie z indeksów jest jedną z rzeczy, która potrafi drastycznie uprościć (i przyspieszyć) manipulowanie danymi w R.

Wszystkie pakiety typu 'plyr' czy 'reshape' bazują właśnie na tym.

Niezłe i zwięzłe omówienie jest np. tutaj:

http://cran.r-project.org/doc/manuals/R-intro.html#Ind...
Marcin Bronicki

Marcin Bronicki kierownik, własna

Temat: problem z replikacją danych

Dzięki za pomoc i dokładne wytłumaczenie.
Wiem gdzie robiłem błąd.

> rozgrupuj2(dane,ilosc)
Error in inherits(x, "factor") : object 'ilosc' not found[quote]rozgrupuj2(dane,dane$ilosc)[/quote]Error: !is.na(vind) is not all TRUE

Kombinowałem i tak i siak, bo nie wiedziałem że trzeba za przecinkiem wyraźnie wpisać vnam="nazwa_kolumny", sądziłem że sama nazwa wystarczy. Ale teraz jest super i mogę się dzięki Wam skupić na właściwych obliczeniach.

Następna dyskusja:

problem z replikacją danych




Wyślij zaproszenie do