2016-05-15 65 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