在特定的可识别行之间对数据进行子集

时间:2015-01-29 03:57:28

标签: r

假设我有一个这样的数据集,在这个例子中有三列。有文本行,在这些行之间是带数字的行(我想要的数据)。如果我想要两个特定文本行之间的数据,您将如何识别特定行,并在行之间对数据进行子集化?例如,假设我想要行与c的行和行与d的数据。

col1 col2 col3
a    a    a
a    a    a
1    1    1
2    2    2
3    3    3
b    b    b
3    3    3
c    c    c
4    4    4
5    5    5
d    d    d

4    4    4
5    5    5

1 个答案:

答案 0 :(得分:6)

如果您需要根据所有列中的相同元素对数据进行子集化,则一个选项是使用interaction粘贴行,使用grep查找与之匹配的行的索引string,获取索引行(:)和子集之间的行序列。

indx1 <-  as.character(interaction(df, sep=''))
indx2 <- grep('ccc|ddd', indx1)
df[(indx2[1]+1):(indx2[2]-1),]
#   col1 col2 col3
#9     4    4    4
#10    5    5    5

在提供的示例中,只有发生这种情况的实例。假设您有多个实例,您可以在cccddd字符串与Map索引,子集和rbind列表元素之间获得相应的序列。

 indx1 <-  as.character(interaction(df1, sep=''))
 do.call(rbind,Map(function(x,y) df1[(x+1):(y-1),],
                   grep('ccc', indx1), grep('ddd', indx1)))

更新

我意识到在数据集中可能存在“ccc”行可能没有对应的“ddd”行或者存在多个“ddd”行等的情况。在这种情况下创建索引(“indx2”)将数据集转换为逻辑矩阵(df2!='c')。对每行(rowSums)求和。结果将是数字向量。这里'0'表示该行具有全部'c'。取消索引(!)以将“0”值转换为“TRUE”和cumsum。将数据集(split)拆分为第一行ccc行之前的行之后的列表。检查每个列表元素中是否都有“d”(!rowSums(x!='d'))行。如果有任何行(if(any(..),则根据索引(x)对数据集(2:(which(i1)[1]-1))进行子集,最后对列表元素进行rbind

 indx2 <- cumsum(!rowSums(df2!='c'))
 lst <- split(df2[indx2!=0,], indx2[!!indx2])
 res <- do.call(rbind,lapply(lst, function(x) {
              i1 <- !rowSums(x!='d')
              if(any(i1)) x[2:(which(i1)[1]-1),]}))

数据

 df <- structure(list(col1 = c("a", "a", "1", "2", "3", "b", "3", "c", 
 "4", "5", "d"), col2 = c("a", "a", "1", "2", "3", "b", "3", "c", 
 "4", "5", "d"), col3 = c("a", "a", "1", "2", "3", "b", "3", "c", 
  "4", "5", "d")), .Names = c("col1", "col2", "col3"), class = 
 "data.frame", row.names = c(NA, -11L))

 df1 <- structure(list(col1 = c("a", "a", "1", "2", "3", "b", "3",
  "c", "4", "5", "d", "3", "b", "3", "c", "4", "5", "d"), col2 = 
  c("a", "a", "1", "2", "3", "b", "3", "c", "4", "5", "d", "3", "b", 
  "3", "c", "4", "5", "d"), col3 = c("a", "a", "1", "2", "3", "b", 
  "3", "c", "4", "5", "d", "3", "b", "3", "c", "4", "5", "d")), .Names 
  = c("col1", "col2", "col3"), class = "data.frame", row.names = c(NA, 
  -18L))

 df2 <- structure(list(col1 = c("a", "a", "1", "2", "3", "b", "3", "c", 
 "4", "5", "d", "3", "b", "3", "c", "4", "5", "d", "4", "5", "d", 
 "c", "4", "5"), col2 = c("a", "a", "1", "2", "3", "b", "3", "c", 
 "4", "5", "d", "3", "b", "3", "c", "4", "5", "d", "4", "5", "d", 
 "c", "4", "5"), col3 = c("a", "a", "1", "2", "3", "b", "3", "c", 
 "4", "5", "d", "3", "b", "3", "c", "4", "5", "d", "4", "5", "d", 
 "c", "4", "5")), .Names = c("col1", "col2", "col3"), class =  
"data.frame", row.names = c(NA, -24L))