2016-05-15 66 views
0

我已經從R中獲得了兩個數據框,這些數據框是從我完成的其他一些東西中生成的。從查找表中應用規則

一個是寬表,包含幾個數字。我們可以稱它們爲x1和x2。這些變量可以取從-999到999的值。

另一個數據框是一個長表,包含var,min,max和group的列。這些本質上是一組if-than規則。下面是一個示例:

# look up table example 
var <- c('x1', 'x1', 'x1', 'x2', 'x2') 
min <- c(-999, 5, 70, -999, 20) 
max <- c(5, 70, 999, 20, 999) 
group <- c(1,2,3,1,2) 
lkup<- data.frame(var, min, max, group) 

表中的數據可以作爲一組if-than語句讀取。例如,這個表c的第一行('x1', - 999,5,1)意味着x1中的-999和5之間的任何值都應該映射到1,我們將把它稱爲y1。表中的所有行都可以用類似的方式解釋。

y1應該從x1獲得所有映射。所以最終應該有與x1規則一樣多的唯一值。

我想要做的是根據df中的數據和查找表中的規則創建一個新的數據框。

因此,舉例來說,如果我有以上在這裏查找表和數據:

# Desired result 
y1 <- c(1, 1, 2, 2, 3) 
y2 <- c(1, 1, 1, 2, 2) 
result <- data.frame(y1, y2) 

我認爲這是:

# data 
x1 <- c(1, 2, 50, 70 , 100) 
x2 <- c(2, 3, 4, 50, 60) 
df <- data.frame(x1, x2) 

我應該看起來像這樣的一個表來結束對我遇到的問題提供了一個絕妙的解決方案,但實際上完成這一任務充滿了挑戰。任何人可以給我的指導將非常感激。

回答

1

使用dplyrtidyr包A液:

library(dplyr); library(tidyr); 
result <- merge(lkup, gather(df, var, value), by = "var") %>%     
      filter(value > min & value <= max) %>% 
      select(var, group) %>%     
      group_by(var) %>% mutate(id = seq_len(n())) %>% 
      spread(var, group) %>% select(-id) 

> result 
Source: local data frame [5 x 2] 

    x1 x2 
    (dbl) (dbl) 
1  1  1 
2  1  1 
3  2  1 
4  2  2 
5  3  2 

採取原始數據集在內的順序,你可以在ID變量添加到您的數據使每個記錄獨特的,可追溯的:

df 
    id x1 x2 
1 1 1 2 
2 2 2 3 
3 3 50 4 
4 4 70 50 
5 5 100 60 
merge(lkup, gather(df, var, value, -id), by = "var") %>% 
    filter(value > min & value <= max) %>% 
    select(id, var, group) %>% spread(var, group) 

    id x1 x2 
1 1 1 1 
2 2 1 1 
3 3 2 1 
4 4 2 2 
5 5 3 2 
+0

這適用於給定的數據,但如果df中的數據順序沒有排序(即看起來不像它已排序),則結果不正確。 – ApeWithPants

+0

如果你的意思是原始數據和結果之間的對應關係,我認爲最好的方法是在原始數據中創建一個id變量,這個變量將保留到結果。否則,您可能需要提供一個示例來說明您的意思? – Psidom