【问题标题】:Concatenate two strings with common elements连接两个具有共同元素的字符串
【发布时间】:2018-08-09 22:32:45
【问题描述】:

我正在研究一个R中的简单问题(但我还没有弄清楚;p):

给定一个向量vect1 <- c("Andy+Pete", "Mary + Pete", "Pete+ Amada", ..., "Amada + Steven", "Steven + Henry")。我想创建一个新向量vect2,其中包含vect1 中的所有元素 共享以下属性的新元素:对于每两个字符串"A+B""B+C",我们将其连接起来进入"A+C" 并将这个新元素添加到vect2。谁能帮我做这件事?

另外,我想得到all每个字符串中+前面的元素,下面的代码正确吗?

for (i in length(vect1)){ vect3[i] <- regexpr(".*+", vect1[i]) }

第三个问题:如果我有一个数据框 dDate 列,格式为 %d-%b(例如,01-Apr),我如何根据 Date 以递增顺序对该数据框进行排序??我们就说d &lt;- c(01-Apr,01-Mar,02-Jan,31-June,30-May)

【问题讨论】:

  • vect1的元素是always两个人,还是1个或3+个?这听起来像是组合“有趣”。
  • 很确定您需要将vect1 拆分为单独的列。
  • 你能举个例子吗?
  • @r2evans:幸运的是,总是两个人。我的for 循环代码如何? @ManishSaraswat Saraswat:是的,一个例子是"Mary + Pete" & "Pete + Amada"(第 2 和第 3 列)= "Mary + Amada"。所以新向量的大小将是vect1 + 所有新的连接元素,就像这样。

标签: r string concat


【解决方案1】:

我认为应该这样做,但我做了一些我可能不应该做的事情......比如增长对象和嵌套 for 循环。如果要访问“+”前面的所有元素,只需使用name.matrix[,1]

vect1 <- c("Andy+Pete", "Mary + Pete", "Pete+ Amada","Amada + Steven", "Steven + Henry")

library(stringr)

name.matrix <- matrix(do.call('rbind',str_split(vect1, pattern = "\\s?[+]\\s?")), ncol = 2)

new.stuff <- c()

for(x in unique(name.matrix[,2])){
  sub.mat.1 <- matrix(name.matrix[name.matrix[,2] == x,], ncol = 2)
  sub.mat.2 <- matrix(name.matrix[name.matrix[,1] == x,], ncol = 2)
  if(length(sub.mat.1) && length(sub.mat.2)){
    for(y in seq_along(sub.mat.1[,2])){
      new.add <- paste0(sub.mat.1[y,1],'+', sub.mat.2[,2])
      new.stuff <- c(new.stuff, new.add)
    }
  }
}

vect2 <- c(vect1, new.stuff)
vect2
#[1] "Andy+Pete"      "Mary + Pete"    "Pete+ Amada"    "Amada + Steven" "Steven + Henry" "Andy+Amada"    
#[7] "Mary+Amada"     "Pete+Steven"    "Amada+Henry" 

更新:

第三个问题。嗯,六月只有30天。所以你会在那里得到一个NA。如果它是您尝试根据日期排序的 data.frame,则需要使用格式df[order(df$Date),]lubridate 包在处理日期时也可能会有所帮助。

d <- c('01-Apr','01-Mar','02-Jan','31-June','30-May')

d.new <- as.Date(d, format = '%d-%b')
d.new <- d.new[order(d.new)]
d.new
#[1] "2018-01-02" "2018-03-01" "2018-04-01" "2018-05-30" NA  

【讨论】:

  • 非常感谢您的帮助。什么解决方案!!您也可以帮忙解答第三个问题吗?
  • 没问题。好的,我写了一个回复。
  • 我试过了,但是 R 刚被冻结(我的数据集有 8556 万+行)。我想知道这是不是因为条目是双引号??
  • 您的数据集有超过 8500 万行?不,我怀疑它被冻结是因为排序那么多行的大小。双引号应该没关系。尝试拆分一个庞大的数据集并对其进行排序,看看它是否有效。
  • 对不起,我一直在旅行。如果它是一个data.frame,它应该和你写的一样。但是我给出的例子只是一个向量,因此你不需要逗号。
【解决方案2】:

我认为您可以(应该)避免for 循环和在不需要时使用外部库。

所以这可能是一个解决方案:

// create data
vect1 <- c("Andy+Pete", "Mary + Pete", "Pete+ Amada", "Amada + Steven", "Steven + Henry")

// create a matrix of pairs with removed white spaces
pairsMatrix <- do.call(rbind, sapply(vect1, function(v) strsplit(gsub(pattern = " ", replacement = "", x = v), "\\+")))

// remove dimnames (not necessary though)
dimnames(pairsMatrix) <- NULL

// for all line of the pairsMatrix, find if second element is somewhere else first element. Bind that with the previous pairs
allPairs <- do.call(rbind, c(list(pairsMatrix), apply(pairsMatrix, 1, function(names) c(names[1], pairsMatrix[names[2]==pairsMatrix[,1], 2]))))

// filter for oneself-relationships
allPairs[allPairs[,1]!=allPairs[,2],]

      [,1]     [,2]    
 [1,] "Andy"   "Pete"  
 [2,] "Mary"   "Pete"  
 [3,] "Pete"   "Amada" 
 [4,] "Amada"  "Steven"
 [5,] "Steven" "Henry" 
 [6,] "Andy"   "Amada" 
 [7,] "Mary"   "Amada" 
 [8,] "Pete"   "Steven"
 [9,] "Amada"  "Henry" 

关于您的最后一点,我认为使用适当的 Date 对象进行简单排序即可。

【讨论】:

  • 可能是更好的解决方案。我懒得避免循环:)。你得到了我的支持。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-09
相关资源
最近更新 更多