dplyr通过评估查找单元格值来突变特定的列

时间:2018-12-03 18:27:19

标签: r dplyr eval

我已经使用等价物,符号和求值法探索了各种选项,但似乎无法获得正确的语法。这是一个示例数据框。

data.frame("A" = letters[1:4], "B" = letters[26:23], "C" = letters[c(1,3,5,7)], "D" = letters[c(2,4,6,8)], "pastecols" = c("B, C","B, D", "B, C, D", NA))
  A B C D pastecols
1 a z a b      B, C
2 b y c d      B, D
3 c x e f   B, C, D
4 d w g h      <NA>

现在假设我想基于pastecols中的查找字符串粘贴来自不同列的值,并且我始终希望包括列A。这是我想要的结果:

  A B C D pastecols  result
1 a z a b      B, C   a z a
2 b y c d      B, D   b y d
3 c x e f   B, C, D c x e f
4 d w g h      <NA>       d

理想情况下,这可以在dplyr中完成。这是我得到的最接近的东西:

x %>% mutate(result = lapply(lapply(str_split(pastecols, ", "), c, "A"), na.omit))
  A B C D pastecols     result
1 a z a b      B, C    B, C, A
2 b y c d      B, D    B, D, A
3 c x e f   B, C, D B, C, D, A
4 d w g h      <NA>          A

3 个答案:

答案 0 :(得分:2)

这是使用pmap进行类似操作的一种方法。 pmap可用于通过捕获每一行作为命名向量来有效地逐行处理数据帧;然后,您可以使用cols选择所需的列名称以作为["pastecols"]进行索引。

大多数匿名函数语法不是tidyverse东西,而是基本的R东西。要遍历它:

  1. 将数据框作为列表传递到.l的{​​{1}}参数。请记住,数据框是列的列表!
  2. 使用pmap_chr捕获所有...参数。基本上,我们将数据帧的每一行称为函数的参数;现在c(...)是包含行的命名向量。请注意,如果您有列表列,则该列会中断,(但是这里的很多其他事情也将中断,所以我认为这里没有...)
  3. 我们可以从row中获得所需的row的值,但是我们需要将row["pastecols"]转换为"B, C"来实现。下一行仅添加c("A", "B", "C"),将丢失的值替换为"A",如果有则拆分成小块,然后向下索引到列表中。 "A"部分就是您在管道链中的操作[[,这是运算符的前缀形式。您需要这样做,因为list[[1]]"返回一个列表,而我们只需要向量。
  4. 使用此str_split向量从cols获取所需的值并将其返回,折叠成长度为1个字符的向量!
row

reprex package(v0.2.0)于2018-12-03创建。

答案 1 :(得分:1)

这不是最优雅的解决方案,但仅需使用基数R即可完成工作。如果A中从未显示列pastecols,则可以从代码中删除unique()

for(r in seq_len(nrow(df))) {
  df$result[r] <- paste(
                    df[r, na.omit(unique(c("A", unlist(strsplit(df$pastecols[r], ", ")))))],
                    collapse = " "
                  )
}
df

  A B C D pastecols  result
1 a z a b      B, C   a z a
2 b y c d      B, D   b y d
3 c x e f   B, C, D c x e f
4 d w g h      <NA>       d

数据-

df <- data.frame(
  "A" = letters[1:4], 
  "B" = letters[26:23], 
  "C" = letters[c(1,3,5,7)], 
  "D" = letters[c(2,4,6,8)], 
  "pastecols" = c("B, C","B, D", "B, C, D", NA), stringsAsFactors = F
)

答案 2 :(得分:1)

这是另一种不依赖applymap系列中的迭代函数的方式,如果您希望避免使用它们,则尝试利用tidyr。该方法基本上是将具有tidyversegather的数据帧扩展为separate_rows和实际列的每种组合,然后扩展为pastecols,因此我们只保留与每个匹配的filter。一旦有了这些,我们就可以rowidgroup_by将其返回到每summarise一行。有很多内务处理来处理您始终拥有列rowid的事实,请注意,我在输出A中保留了A,但是如果您想删除它,可以删除它

pastecols

reprex package(v0.2.0)于2018-12-03创建。