从数据框中删除那些列被其他列所包含的行

3
我正在尝试在数据框中实现类似于unique的操作,其中行中每个列元素都是向量。我想要做的是,如果该行中列的向量元素是另一个向量的子集或相等,则删除具有较少元素数的行。使用嵌套的for循环可以实现此操作,但由于数据包含400,000行,程序效率非常低。 样例数据:
# Set the seed for reproducibility 
set.seed(42)

# Create a random data frame
mydf <- data.frame(items = rep(letters[1:4], length.out = 20), 
                   grps = sample(1:5, 20, replace = TRUE),
                   supergrp =  sample(LETTERS[1:4], replace = TRUE))


# Aggregate items into a single column
temp <- aggregate(items ~ grps + supergrp, mydf, unique)

# Arrange by number of items for each grp and supergroup 
indx <- order(lengths(temp$items), decreasing = T)
temp <- temp[indx, ,drop=FALSE]

临时文件的外观如下

       grps supergrp   items
    1     4        D a, c, d
    2     3        D    c, d
    3     5        D    a, d
    4     1        A       b
    5     2        A       b
    6     3        A       b
    7     4        A       b
    8     5        A       b
    9     1        D       d
   10     2        D       c

现在您可以看到第二行和第三行的超组和项目的第二个组合包含在第一行中。因此,我想从结果中删除第二行和第三行。同样,第5到8行包含在第4行中。最后,第9和第10行包含在第一行中,所以我想删除第9和第10行。因此,我的结果应该如下:

      grps supergrp   items
    1    4        D a, c, d
    4    1        A       b 

我的实现如下:

# initialise the result dataframe by first row of old data frame
newdf <-temp[1, ]

# For all rows in the the original data
for(i in 1:nrow(temp))
{
  # Index to check if all the items are found 
  indx <- TRUE

  # Check if item in the original data appears in the new data
  for(j in 1:nrow(newdf))
  {
   if(all(c(temp$supergrp[[i]], temp$items[[i]]) %in% 
          c(newdf$supergrp[[j]], newdf$items[[j]]))){
     # set indx to false if a row with same items and supergroup  
     # as the old data is found in the new data
    indx <- FALSE
   }
  }

  # If none of the rows in new data contain items and supergroup in old data append that
  if(indx){
    newdf <- rbind(newdf, temp[i, ])
  }
}

我相信有一种有效的方法可以在R中实现这个,可能使用tidy框架和dplyr链,但我不知道诀窍。对于一个比较长的问题,我感到抱歉。任何意见将不胜感激。


听起来像是一个网络/图问题。您可以使用igraph包找到将每个grp/supergrp配对链接到items的图形,然后您可以为每个组分配一个“集群”,以确定共享哪些items - thelatemail
例如,您可以像 library(igraph); int <- interaction(mydf[c("grps","supergrp")]); g <- graph.data.frame(cbind(mydf["items"],int)); clg <- clusters(g); mydf$clusters <- clg$membership[match(int, names(clg$membership))] 这样分配集群标识符。 - thelatemail
1个回答

1
我会尝试从列表列中获取项目并将它们存储在一个更长的数据框中。以下是我的解决方案,有些不太正宗:
library(stringr)

items <- temp$items %>% 
    map(~str_split(., ",")) %>% 
    map_df(~data.frame(.))

out <- bind_cols(temp[, c("grps", "supergrp")], items)

out %>% 
    gather(item_name, item, -grps, -supergrp) %>% 
    select(-item_name, -grps) %>% 
    unique() %>% 
    filter(!is.na(item))

有没有一种方法可以在结果中悄悄地插入“grps”字段? - discipulus
我认为你可以使用distinct(supergrp, item)代替unique() - Shorpy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接