基于一帧的一列和另一列

时间:2016-08-02 04:23:47

标签: r

所以我有两个数据框,信息和塔,下面有例子:

的信息:

ID             Date
1132           01/09/2015
1156           02/09/2015
1132           04/09/2015
1101           04/09/2015

塔:

Tower   ID1   ID2
    1   1132  1101
    2   1520  1156

Info的ID列中的值将始终与Towers中的ID1或ID2匹配。我想根据这些信息加入框架,所以我加入的框架应该是:

ID             Date         Tower
1132           01/09/2015       1
1156           02/09/2015       2
1132           04/09/2015       1
1101           04/09/2015       2

我知道dplyr的semi_join会产生类似我需要的东西,但我知道它需要在值和列名称中匹配。鉴于这些列有不同的名称,我不知道它是否会正常工作。有没有我可以在这里使用的方法?

4 个答案:

答案 0 :(得分:3)

library(dplyr)

tidyr::gather(df2, Tower2, ID, -Tower) %>% select(-Tower2) %>% right_join(df, "ID")

<强> DF

structure(list(ID = c(1132, 1156, 1132, 1101), Date = structure(c(1L, 
2L, 3L, 3L), .Label = c("01/09/2015", "02/09/2015", "04/09/2015"
), class = "factor")), .Names = c("ID", "Date"), row.names = c(NA, 
-4L), class = "data.frame")

<强> DF2

structure(list(Tower = 1:2, ID1 = c(1132L, 1520L), ID2 = c(1101L, 
1156L)), .Names = c("Tower", "ID1", "ID2"), class = "data.frame", row.names = c(NA, 
-2L))

答案 1 :(得分:2)

我们可以使用melt中的data.table。转换&#39; data.frame&#39;到&#39; data.table&#39; (setDT(df2)),melt来自&#39;范围&#39;长期&#39;格式和join与原始数据集&#39; df&#39; on&#39; ID&#39;。

library(data.table)
melt(setDT(df2), id.var="Tower", value.name = "ID")[df, on = "ID"][, variable := NULL][]
#  Tower   ID       Date
#1:     1 1132 01/09/2015
#2:     2 1156 02/09/2015
#3:     1 1132 04/09/2015
#4:     1 1101 04/09/2015

我们也可以在没有任何连接的情况下执行此操作,并且仅使用base R(没有外部包,没有任何循环(sapply是伪装的循环))。在这里,我们的想法是复制第二个数据集&#39; Tower&#39;列数除了&#39; Tower&#39;之外的列数。即2,通过names&lt; df2&#39}的列设置该向量的unlist。除了&#39; Tower&#39; (unlist(df2[-1]))并使用它来匹配&#39; ID&#39;第一个数据集(as.character(df$ID))中的列,用于返回&#39; Tower&#39;对应于&#39; ID&#39;。

df$Tower <- setNames( rep(df2$Tower, 2), unlist(df2[-1]))[as.character(df$ID)]
df$Tower
#[1] 1 2 1 1

答案 2 :(得分:1)

使用melt包并使用reshape2&amp;和df来使用df2(@SymbolixAU在评论中建议)的另一种方法{@ 1}} @ Sumedh的帖子。

library(reshape2)
library(dplyr)
melt(df2,value.name = "ID",id.vars = "Tower") %>% right_join(df,by = "ID") %>% select(-variable)

我们也可以使用base R reshape函数执行此操作:

reshape(data = df2,direction = "long",varying = c("ID1","ID2"),v.names = "ID") %>% right_join(df,by = "ID") %>% select(-c(time,id))

答案 3 :(得分:1)

你真的不需要加入;只要按行分组评估,就可以创建一个新列:

Info %>% rowwise() %>% 
    mutate(Tower = Towers[ID == Towers$ID1 | ID == Towers$ID2, 'Tower'])
## Source: local data frame [4 x 3]
## Groups: <by row>
## 
## # A tibble: 4 x 3
##      ID       Date Tower
##   <int>     <fctr> <int>
## 1  1132 01/09/2015     1
## 2  1156 02/09/2015     2
## 3  1132 04/09/2015     1
## 4  1101 04/09/2015     1

或等效于完全基础R,

Info$Tower <- sapply(Info$ID, function(x){Towers[x == Towers$ID1 | x == Towers$ID2, 'Tower']})