【问题标题】:R subset vector when treated as strings将 R 子集向量视为字符串时
【发布时间】:2017-04-29 17:05:27
【问题描述】:

我有一个大型数据框,我已将向量强制转换为字符串(使用 lapply 和 toString),以便它们适合数据框,现在我无法检查一列是否是另一列的子集。有没有一种简单的方法可以做到这一点。

X <- data.frame(y=c("ABC","A"), z=c("ABC","A,B,C"))

 X
      y     z
1   ABC   ABC
2    A   A,B,C


all(X$y %in% X$z)
[1] FALSE

(X$y[1] %in% X$z[1])
[1] TRUE

(X$y[2] %in% X$z[2])
[1] FALSE

我需要再次将每个 y 和 z 字符串值视为一个向量(逗号分隔),然后检查 y 是否是 z 的子集。

在上述情况下,A 是 A,B,C 的子集。但是,因为我将两者都视为字符串,所以它不起作用。

在上面,y 只是一个值,z 是 1 和 3。我要测试的数据帧样本是 10,000 行,y 每行有 1-5 个值,z 每行有 1-100 个值。看起来 1-5 始终是 z 的子集,但我想检查一下。

【问题讨论】:

  • 尝试使用apply(X, 1, function(x) x[1] %in% unlist(strsplit(x[2], ",")))
  • 你每行只有一个字符串不清楚你想要什么as.character(X[,1])==as.character(X[,2])或者可能是mapply(grepl, X$y, X$z)
  • 试试grepl(X$y[2], X$z[2])mapply(grepl, X$y, X$z)
  • 实际上你需要定义你是否想要完美的子集。例如如果X$y[2] == "A,B,D",那么您期望的输出是什么?
  • @Sotos 可能添加 fixed=TRUE 会起作用(我怀疑“++”会导致错误),但没有真实数据,无法确定。

标签: r string vector subset


【解决方案1】:
df = data.frame(y=c("ABC","A"), z=c("ABC","A,B,C"))

apply(df, 1, function(x) {               # perform rowise ops.
  y = unlist(strsplit(x[1], ","))        # splitting X$y if incase it had ","  
  z = y %in% unlist(strsplit(x[2], ",")) # check how many of 'X$y' present in 'X$z'
  if (sum(z) == length(y))               # if all present then return TRUE
    return(TRUE)
  else
    return(FALSE)
})

# 1] TRUE TRUE

# Case 2: changed the data. You will have to define if you want perfect subset or not. Accordingly we can update the code
df = data.frame(y=c("ABC","A,B,D"), z=c("ABC","A,B,C"))
#[1]  TRUE FALSE

【讨论】:

  • 谢谢!这很好用。看起来它唯一显示错误的时间是 z 以逗号结尾,然后在 y 中放置一个双逗号。
  • 当 X$z 的所有元素都不存在于 X$y 中时,它显示 FALSE
  • 如果你想要TRUE,即使 X$z 中存在 X$y 的单个元素,然后将 return 替换为 return(ifelse(any(z), TRUE, FALSE))
【解决方案2】:

我认为最好不要使用 lapplytoString 组合,而是将列表存储在数据框中。为此,我发现tbl_df(在tibble 包中找到)更友好,尽管我相信data.table 对象也可以做到这一点(如果我错了,请有人纠正我)

library(tibble)

y_char <- list("ABC", "A")
z_char <- list("ABC", c("A", "B", "C"))

X <- data_frame(y = y_char, 
                z = z_char)

请注意,当您现在打印X 时,tibble 每一行中的条目都是列表中的条目。现在我们可以使用mapply进行两两比较。

# All y in z
mapply(function(x, y) all(x %in% y),
       X$y,
       X$z)


# All z in y
mapply(function(x, y) all(y %in% x),
       X$y,
       X$z)

【讨论】:

  • 如果你看到我的代码长度你会同意我不会重写它哈哈,我以后一定会记住这一点的,谢谢!一个问题,当您查看数据框时,您会看到 c("A", "B", "C")。所以我想它也会被写入这样的csv,这可能会有问题。
  • write.csv 在我尝试使用列表格式编写它时踢出错误。错误消息是unimplemented type 'list' in 'EncodeElement'。因此,如果需要,您根本无法将其写入 csv。您必须有意识地决定如何以平面格式存储它。
猜你喜欢
  • 2020-05-09
  • 1970-01-01
  • 1970-01-01
  • 2020-10-17
  • 1970-01-01
  • 2018-12-07
  • 2015-07-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多