如果列中存在字符串,则检查相邻单元格,写入循环,简洁代码,子集数据帧

时间:2017-01-09 21:50:39

标签: r

我有一个相对较大的数据集,我想测试每个sting是否存在于从较大数据集创建的一系列子集数据帧中。 我能够通过三个步骤完成此任务,但我想编写一段代码,只需一步即可完成。

由于我想要的文件大小 创建子文件t2.a用于在我的文件t1中添加1或0,删除它; 然后重复t2.b,t2.c ...

的过程

我的实际数据集类似于下面的数据帧。

t1 <- data.frame(A1 = c("red", "blue", "green", "yellow", "brown"),
                 A2 = c("orange", "purple", "yellow", "black", NA),
                 A3 = c(1,2,4,5,7))

t2 <- data.frame(B2 = c("black", "pink", "lime", "green", "grey", "mist", "blond", "grass", "violet", "red"),
                 B3 = c("a", "b", "a", "c", "d", "d", "a" , "c", "a", "b"))

> t1
      A1     A2 A3
1    red orange  1
2   blue purple  2
3  green yellow  4
4 yellow  black  5
5  brown   <NA>  7

> t2
       B2 B3
1   black  a
2    pink  b
3    lime  a
4   green  c
5    grey  d
6    mist  d
7   blond  a
8   grass  c
9  violet  a
10    red  b

我现有的代码分为三个步骤:

# step 1. creates a subset of files 
for(i in unique(t2$B3)) {
    colName <- paste("t2", i, sep = ".")
    assign(colName, t2[t2$B3 == i, ])    
}

# step2. find if string exist in a given subfile
t1$t2.a <- ifelse(t1$A1 %in% t2.a$B2 | t1$A2 %in% t2.a$B2, 1, 0)
#
t1$t2.b <- ifelse(t1$A1 %in% t2.b$B2 | t1$A2 %in% t2.b$B2, 1, 0)
#
t1$t2.c <- ifelse(t1$A1 %in% t2.c$B2 | t1$A2 %in% t2.c$B2, 1, 0)
#
t1$t2.d <- ifelse(t1$A1 %in% t2.d$B2 | t1$A2 %in% t2.d$B2, 1, 0)

# 3.remove each newly created data set 
rm(t2.a)
rm(t2.b)
rm(t2.c)
rm(t2.d) 

结果应该如下面的数据框:

      A1     A2 A3 t2.a t2.b t2.c t2.d
1    red orange  1    0    1    0    0
2   blue purple  2    0    0    0    0
3  green yellow  4    0    0    1    0
4 yellow  black  5    1    0    0    0
5  brown   <NA>  7    0    0    0    0

2 个答案:

答案 0 :(得分:2)

以下内容可实现您想要的结果。

我们不是多次重复相同的代码块,而是更改参数,而是利用R lapply

它实际上是lapply内的几个步骤,但只需一次通话。

cbind(t1,
      do.call(what = cbind,
              args = lapply(unique(t2$B3), function(var_x){
                colName <- paste("t2", var_x, sep = ".")
                df <- assign(colName, t2[t2$B3 == var_x, ])
                df_2 <- data.frame(ifelse(t1$A1 %in% df$B2|t1$A2 %in% df$B2, 1, 0))
                colnames(df_2) <- paste("t2", as.character(var_x), sep = ".")
                df_2})
      )
)

答案 1 :(得分:1)

有很多方法可以做到这一点,但你需要一个[左]连接,然后扩展到宽范围。一个选项:

t3 <- merge(t1, t2, by.x = 'A1', by.y = 'B2', all.x = TRUE)    # add matching values of B3
t3 <- merge(t1, xtabs(rep(1, nrow(t3)) ~ A1 + B3, t3))    # spread B3 with xtabs, rejoin

t3 <- tidyr::spread(t3, B3, Freq)    # for the life of me I can't figure out stats::reshape

t3
##       A1     A2 A3 a b c d
## 1   blue purple  2 0 0 0 0
## 2  brown   <NA>  7 0 0 0 0
## 3  green yellow  4 0 0 1 0
## 4    red orange  1 0 1 0 0
## 5 yellow  black  5 0 0 0 0

或者,如果您使用cbindas.data.frame.matrix表格显式转换为data.frame,则可以使用xtabs代替第二次加入和传播:

t3 <- merge(t1, t2, by.x = 'A1', by.y = 'B2', all.x = TRUE)
t3 <- cbind(t1, as.data.frame.matrix(xtabs(rep(1, nrow(t1)) ~ A1 + B3, t3)))

使用一些额外的rownames返回相同的内容。