【问题标题】:concatenate iteratively first/last n words from strings迭代地连接字符串中的第一个/最后 n 个单词
【发布时间】:2020-03-28 03:34:19
【问题描述】:

假设我有以下data.frame:

df <- data.frame(string=c("word1 word2 word3 word4", "word1 word2", "word1"), stringsAsFactors = FALSE)

我想在一个列表(或每行)中导出第一个/最后 n 个单词(n 从 1 到单词数)的串联。预期结果:

list(
string1=c('left1'="word1", 'left2'= "word1 word2", 'left3'="word1 word2 word3",
          'left4'="word1 word2 word3 word4",
        'right1'="word4", 'right2'="word3 word4", 'right3'="word2 word3 word4"),
string2= c('left1'="word1", 'left2'="word1 word2", 'right1'="word2"),
string3="word1")

(根本不需要但便于理解的元素名称)。

不想要:粘贴中间元素,例如“word2 word3”。

我目前使用strsplit(df$string) 准备所需列表的第一步,然后可以通过双循环实现我想要的,但这远非高效。

基本 R / data.table 中首选的方法,但 tidyverse 有效的解决方案会很好。

【问题讨论】:

  • 你需要左边的 i 是 1 到 n 和右边的 i 是 1 到 n-1?
  • 从 1 到 n 的所有 lefti i 都正确;右 i: n-1 到 n

标签: r string data.table combinations word


【解决方案1】:

感谢 Ronak 方法(谢谢),我最终得到了以下代码。 比我的循环更优雅、更高效。

paste_words_left <- function(x) {
 sapply(seq_along(x), function(y) paste0(x[1:y], collapse = " "))
}

paste_words_right <- function(x) {
 sapply(seq_along(x)[-1], function(y) paste0(x[y:length(x)], collapse = " "))
}

## lapply(strsplit(df$string, " "), function(x) c(paste_words_left(x), paste_words_right(x)))

lapply(strsplit(df$string, " "), function(x){
  if (length(x)==1) x else  c(paste_words_left(x), paste_words_right(x))})

【讨论】:

  • 已更新,长度为 1 的向量的输出不正确(将字符串与空列表连接会导致列表)。我将错误的行放在评论中并更新了我的代码。
【解决方案2】:

基础 R 版本:

我们可以编写一个函数,以递增方式粘贴每次添加每个单词的值。

paste_words <- function(x) {
   sapply(seq_along(x), function(y) paste0(x[1:y], collapse = " "))
}

lapply(strsplit(df$string, " "), function(x) c(paste_words(x), paste_words(rev(x))))


#[[1]]
#[1] "word1"    "word1 word2"    "word1 word2 word3"   "word1 word2 word3 word4"
#[5] "word4"    "word4 word3"     "word4 word3 word2"  "word4 word3 word2 word1"

#[[2]]
#[1] "word1"    "word1 word2" "word2"    "word2 word1"

#[[3]]
#[1] "word1" "word1"

您可能需要将unique 包装起来,以避免在最后一个元素中重复类似的单词。

【讨论】:

  • 嗨,这并不是我们想要的:xrev(x) 的处理方式不同。对于正确/最后的话,我们想要例如"word2 word3 word4" "word3 word4" "word3"。但是您的功能对我来说似乎不错,我将其用作我建议的模板。参考我的帖子。
【解决方案3】:

dplyrtidyrpurrr 选项可以是:

df %>%
 rowid_to_column() %>%
 separate_rows(string, sep = " ") %>%
 group_by(rowid) %>%
 transmute(concatenated = accumulate(string, ~ paste(.x, .y)),
           concatenated_rev = accumulate(rev(string), ~ paste(.x, .y)))

  rowid concatenated            concatenated_rev       
  <int> <chr>                   <chr>                  
1     1 word1                   word4                  
2     1 word1 word2             word4 word3            
3     1 word1 word2 word3       word4 word3 word2      
4     1 word1 word2 word3 word4 word4 word3 word2 word1
5     2 word1                   word2                  
6     2 word1 word2             word2 word1            
7     3 word1                   word1   

或者有更多的左/右信息:

df %>%
 rowid_to_column() %>%
 separate_rows(string, sep = " ") %>%
 group_by(rowid) %>%
 transmute(left = paste0("left", 1:n()),
           concatenated = accumulate(string, ~ paste(.x, .y)),
           right = paste0("right", 1:n()),
           concatenated_rev = accumulate(rev(string), ~ paste(.x, .y)))

  rowid left  concatenated            right  concatenated_rev       
  <int> <chr> <chr>                   <chr>  <chr>                  
1     1 left1 word1                   right1 word4                  
2     1 left2 word1 word2             right2 word4 word3            
3     1 left3 word1 word2 word3       right3 word4 word3 word2      
4     1 left4 word1 word2 word3 word4 right4 word4 word3 word2 word1
5     2 left1 word1                   right1 word2                  
6     2 left2 word1 word2             right2 word2 word1            
7     3 left1 word1                   right1 word1 

【讨论】:

  • 嗨 tmfmnk,与我在 Ronak 解决方案上发布的评论相同。对不起,如果我的问题不够清楚。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-31
  • 1970-01-01
  • 2022-12-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多