比较两个不相等的数据帧并按第二数据帧的顺序选择公共值

时间:2017-08-23 07:03:47

标签: r dataframe

我有两个数据框如下:

df1<-data.frame(st=c(1,2,3,4),v1=c(12,14,15,75),v2=c(43,32,12,18))

df1
  st v1 v2
1  1 12 43
2  2 14 32
3  3 15 12
4  4 75 18

df2<-data.frame(st=c(1,2,3,4),v1=c(12,24,35,18),v2=c(48,32,121,82),v3=c(53,11,12,75))

df2
  st v1  v2 v3
1  1 12  48 53
2  2 24  32 11
3  3 35 121 12
4  4 18  82 75

我想要的是匹配&#34; st&#34;列级别,即对于df1中的st = 1,v1和v2的对应值是12&amp; 43.因此,如果df2中的st = 1,如果任何变量包含这些值,那么我想从df2中选择st和那些值。

因此,对于上面的示例,输出将是

St values
1     12(coming from v1 in df2)
2     32(coming from v2 in df2)
3     12(coming from v3 in df2)
4     18 75(coming from v1 & v3 in df2)

需要注意的重要一点是,在输出数据框中,所选变量的顺序应该与df2的顺序一样,因为你可以看到,对于st = 4,df1中的值是75&amp; 18与st = 2匹配,但输出仍为18,然后是75,这是df2中的顺序。 df2中的变量也总是大于df1。

2 个答案:

答案 0 :(得分:1)

如果我理解正确的话......

步骤0.准备数据

您提到您只想选择符合条件的行,但样本数据集在每行中至少有一个匹配项。我调整它以使得St = 3不匹配,以证明结果中不会返回该行。

df1<-data.frame(st=c(1,2,3,4),v1=c(12,14,15,75),v2=c(43,32,12,18))
df2<-data.frame(st=c(1,2,3,4),v1=c(12,24,35,18),v2=c(48,32,121,82),v3=c(53,11,13,75))

步骤1.合并数据集

combined.df <- rbind(df1 %>% gather(v, n, -st) %>% mutate(df = "df1"),
                     df2 %>% gather(v, n, -st) %>% mutate(df = "df2"))

> head(combined.df)
  st  v  n  df
1  1 v1 12 df1
2  2 v1 14 df1
3  3 v1 15 df1
4  4 v1 75 df1
5  1 v2 43 df1
6  2 v2 32 df1

第2步。比较&amp;只保留df2中匹配的那些

res <- combined.df %>%
  group_by(st) %>%
  mutate(n = ifelse(df=="df1", n, ifelse(n %in% n[df=="df1"], n, NA))) %>%
  ungroup() %>%
  filter(df=="df2", !is.na(n)) %>%
  arrange(st, v)
# if you just want the values, you can stop here.
> res
# A tibble: 4 × 4
     st     v     n    df
  <dbl> <chr> <dbl> <chr>
1     1    v1    12   df2
2     2    v2    32   df2
3     4    v1    18   df2
4     4    v3    75   df2


# this part formats the result to follow that of the desired output
res <- res %>%
  group_by(st) %>%
  summarise(values = paste(as.character(n), collapse = " ")) %>%
  ungroup()
> res
# A tibble: 3 × 2
     st values
  <dbl>  <chr>
1     1     12
2     2     32
3     4  18 75

答案 1 :(得分:0)

如果您使用合并功能,则可以使用以下匹配项创建唯一的df:

new<-merge(df1,df2,by="st")

new

  st v1.x v2.x v1.y v2.y v3
1  1   12   43   12   48 53
2  2   14   32   24   32 11
3  3   15   12   35  121 12
4  4   75   18   18   82 75

如果您愿意,您可以按照自己的方式订购。例如:

new2<-new[,1:2]
new2$from<-"from v1"
names(new2)<-c("st","value","from")


for(i in 3:ncol(new)){
new3<-new[,c(1,i)]
new3$from<-pasteo("from v",i)
names(new3)<-c("st","value","from")
new2<-rbind(new2,new3)

}

这不是最有效的方法,但如果你的数据很少,它就会起作用