2016-04-08 10 views
5

Mam ramkę danych z danymi tygodniowymi według sekcji. Każda sekcja ma dane o długości 104 tygodni i zawiera 83 sekcje.Scalanie/dołączanie ramki danych/tabeli na podstawie kryteriów -> lub <

Mam drugą ramkę danych z początkiem i końcem tygodnia według sekcji, którą chcę filtrować główną ramkę danych.

W obu tabelach Tydzień jest kombinacją roku i tygodnia, np. 201501 i jest zawsze od tygodni 1 do 52.

Dlatego w poniższym przykładzie chcę filtrować Sekcji A przez tygodnie 201401 do 201404, Sekcja B od tygodni 201551 do 201603.

I początkowo myślałem, że mogę dodać dodatkową kolumnę do ramki danych Weeks_Filter, która jest kolejnym numerem od początku i końca tygodnia dla każdej sekcji (duplikowanie każdego wiersza dla każdego tygodnia), a następnie scalenie 2 tabel i zachowanie wszystkich danych z tabeli Weeks_Filter (wszystkie. y = TRUE), ponieważ działało to na małej próbce, którą zrobiłem, ale nie wiem, jak dodać sekwencyjne tygodnie, ponieważ mogą one obejmować różne lata.

Week <- c("201401","201402","201403","201404","201405", "201451", "201552", "201601", "201602", "201603") 
Section <- c(rep("A",5),rep("B",5)) 
df <- data.frame(cbind(Week, Section)) 

Section <- c("A", "B") 
Start <- c("201401","201551") 
End <- c("201404","201603") 
Weeks_Filter <- data.frame(cbind(Section, Start, End)) 

Odpowiedz

-2
require(data.table) 

df <- merge(df, Weeks_Filter) 
df[, -1] <- apply(df[, -1], 2, function(x) as.numeric(as.character(x))) 
df <- data.table(df) 

df[Week >= Start & Week <= End, .SD, by = Section] 

Wyjście jest

Section Start End Week 
1:  A 201401 201404 201401 
2:  A 201401 201404 201402 
3:  A 201401 201404 201403 
4:  A 201401 201404 201404 
5:  B 201551 201603 201552 
6:  B 201551 201603 201601 
7:  B 201551 201603 201602 
8:  B 201551 201603 201603 
+0

Dziękuję. Działało idealnie. – MidnightDataGeek

+0

Zastanawiam się, dlaczego odpowiedź brzmi, jak zdobyć głos. Czy ludzie lubią złożone rozwiązania, a nie prostsze. – TheRimalaya

+0

Odpowiedź działała dobrze dla mnie. Jestem nowy w R i pomimo tego, że korzystałem z linku podanego poniżej, nie byłem w stanie uzyskać odpowiedzi. – MidnightDataGeek

1

Korzystanie dplyr można

  • połączyć ramki danych
  • grupę w sekcji
  • filtr oparty na kolumnach początku i na końcu

Jednym z problemów jest to, że " tygodnie są postaciami i stają się czynnikami w taki sposób, w jaki je zakodowałeś. Użyłem skrótu i ​​po prostu zrobiłem je numeryczne, ale polecam użycie lubridate, aby utworzyć odpowiednie wektory klasy Date.

library(dplyr) 
tempdf <- full_join(df, Weeks_Filter) 
tempdf$Week <- as.numeric(as.character(tempdf$Week)) 
tempdf$Start <- as.numeric(as.character(tempdf$Start)) 
tempdf$End <- as.numeric(as.character(tempdf$End)) 


tempdf_filt <- tempdf %>% 
    group_by(Section) %>% 
    filter(Week >= Start, 
     Week <= End) 

Wygląda na to, że jest to problem w swoich danych, że „201451” powinno być „201551”, ale w przeciwnym razie zwraca co chcesz:

> tempdf_filt 
Source: local data frame [8 x 4] 
Groups: Section [2] 

    Week Section Start End 
    (dbl) (fctr) (dbl) (dbl) 
1 201401  A 201401 201404 
2 201402  A 201401 201404 
3 201403  A 201401 201404 
4 201404  A 201401 201404 
5 201552  B 201551 201603 
6 201601  B 201551 201603 
7 201602  B 201551 201603 
8 201603  B 201551 201603 
+1

rok ma 52 tygodni;) – eddi

+0

@ johnSG Dziękuję - miałem tam literówkę. Próbuję opanować data.table, więc użyłem tego, ale to też działało dobrze. – MidnightDataGeek

+0

@eddi Miałem literówkę wskazującą na literówkę (karmę). 201501 -> 201551. naprawiony teraz – JohnSG

0

Może tworząc wektor wszystkich pożądanych tygodni będzie działać dla filtra. Tutaj jest szorstka przykład stosując zasady R:

# get weeks 
allWeeks <- as.character(1:52) 
allWeeks <- ifelse(nchar(allWeeks)==1, paste0("0",allWeeks), allWeeks) 
# get all year-weeks 
allWeeks <- paste0(2014:2015, allWeeks) 

# filter vector to select desired weeks 
keepWeeks <- keepWeeks[grep("201(40[1-4]|55[12]|60[123]))", allWeeks)] 

dfKeeper <- df[df$Week %in% keepWeeks,] 

próbowałem skonstruować wyrażenie regularne, które uchwycić okresy, które chcesz, ale być może trzeba będzie dostosować go trochę.

4

Najnowszy development version z data.table dodaje non-equi przyłącza (aw starszych można użyć foverlaps):

setDT(df) # convert to data.table in place 
setDT(Weeks_Filter) 

# fix the column types - you have factors currently, converting to integer 
df[, Week := as.integer(as.character(Week))] 
Weeks_Filter[, `:=`(Start = as.integer(as.character(Start)), 
        End = as.integer(as.character(End)))] 

# the actual magic 
df[df[Weeks_Filter, on = .(Section, Week >= Start, Week <= End), which = T]] 
#  Week Section 
#1: 201401  A 
#2: 201402  A 
#3: 201403  A 
#4: 201404  A 
#5: 201552  B 
#6: 201601  B 
#7: 201602  B 
#8: 201603  B 
+4

możemy również użyć prefiksu 'x' teraz ... (szczególnie przydatne w odniesieniu do kolumn dołączających x)' df [Weeks_Filter,. (X.Week, Section), on =. (Section, Week> = Start, Week < = End)] ' – Arun

+0

@eddi dzięki za odpowiedź. Nie udało mi się odtworzyć odpowiedzi i myślę, że dzieje się tak, ponieważ nie mam tej samej wersji pliku data.table. Błąd, który miałem: nie mógł znaleźć funkcji "." – MidnightDataGeek

+0

Użyj linku w odpowiedzi, aby uzyskać najnowszą wersję. – eddi

Powiązane problemy