【问题标题】:Is it possible to delete some rows in .x of purrr:::iwalk?是否可以删除 purrr:::iwalk 的 .x 中的某些行?
【发布时间】:2019-05-10 13:57:03
【问题描述】:

我像这样使用 purrr:::iwalk,但它并没有达到我想要的效果:

purrr:::iwalk(DGE_tables, ~ .x[-which(.x$column1 %in% VectorOfSpecificValues),])

DGE_tables 是数据框列表。在这所有数据框中,我想删除在 column1 中具有特定值的行。数据帧具有相同的结构。

是否可以使用 purrr:::iwalk 做到这一点?还是有更好的方法来做到这一点?

编辑:一个例子:

数据框列表:

DGE_tables
# Display
$dataframe1
    column1   column2
1   to_delete    56
2   to_keep      45

$dataframe2
    column1   column2
1   to_delete    78
2   to_keep      27

...

所以我想删除 $column1 = "to_delete" 的行。像这样:

# wanted result
$dataframe1
    column1   column2
1   to_keep      45

$dataframe2
    column1   column2
1   to_keep      27

...

【问题讨论】:

  • 你能展示一个可重现的小例子吗
  • 为什么不简单地map(DGE_tables, ~filter(.x, column1 != "to_delete"))
  • walk 函数用于产生副作用——它们本身不会返回任何东西。它们对于保存文件很有用,然后继续使用您保存的数据。您可能需要一个 map 函数,它会执行您的操作,然后将返回的数据帧传递给下一个管道步骤
  • @r2evans 是的,谢谢。我永远无法完全正确地解释它们。 walk 绝对是棘手的。 map 更适合这种情况。
  • 它返回任何东西的事实是(我猜)允许它在管道中间工作,而不仅仅是在末端。如果这不是一个考虑因素,那么在我看来,任何在任何 prog 语言中调用类似“walk”的函数的东西都可能不会安全地假设任何返回值,因为它的意图是副作用。 *耸耸肩*

标签: r list dataframe purrr


【解决方案1】:

purrrkeep()discard() 只是为了这种事情:

library(purrr)

l <- list(
    list(col1 = 'to keep', col2 = 1),
    list(col1 = 'to discard', col2 = 2)
)

purrr::keep(l, ~ .x[['col1']] == 'to keep')
#> [[1]]
#> [[1]]$col1
#> [1] "to keep"
#> 
#> [[1]]$col2
#> [1] 1
purrr::discard(l, ~ .x[['col1']] == 'to discard')
#> [[1]]
#> [[1]]$col1
#> [1] "to keep"
#> 
#> [[1]]$col2
#> [1] 1

【讨论】:

    【解决方案2】:

    这里有一些事情在起作用。因为我没有你的数据(还没有?),我会自己做,相当粗糙:

    dge <- list(mtcars[1:5,], mtcars[1:5,])
    

    一些问题:

    1. 根据定义,purrr::walkpurrr::iwalk 返回原始帧 .x无论您在功能块中做什么。举个例子,看看这个:

      (purrr::iwalk(dge, ~ return(NULL)))
      # [[1]]
      #                    mpg cyl disp  hp drat    wt  qsec vs am gear carb
      # Mazda RX4         21.0   6  160 110 3.90 2.620 16.46  0  1    4    4
      # Mazda RX4 Wag     21.0   6  160 110 3.90 2.875 17.02  0  1    4    4
      # Datsun 710        22.8   4  108  93 3.85 2.320 18.61  1  1    4    1
      # Hornet 4 Drive    21.4   6  258 110 3.08 3.215 19.44  1  0    3    1
      # Hornet Sportabout 18.7   8  360 175 3.15 3.440 17.02  0  0    3    2
      # [[2]]
      #                    mpg cyl disp  hp drat    wt  qsec vs am gear carb
      # Mazda RX4         21.0   6  160 110 3.90 2.620 16.46  0  1    4    4
      # Mazda RX4 Wag     21.0   6  160 110 3.90 2.875 17.02  0  1    4    4
      # Datsun 710        22.8   4  108  93 3.85 2.320 18.61  1  1    4    1
      # Hornet 4 Drive    21.4   6  258 110 3.08 3.215 19.44  1  0    3    1
      # Hornet Sportabout 18.7   8  360 175 3.15 3.440 17.02  0  0    3    2
      

      (如果您只使用purrr::iwalk(dge, ...) 而不使用周围的括号,您将看不到任何内容,因为默认是返回返回值不可见。括号强制它可见。)

      因此,这里的难点是您在iwalk 中仅过滤的示例将不起作用。为此,您可能需要purrr::imap。 (如果您做得更多,并且您的问题中的小例子是更短的 sn-p 更多代码,那么您可能仍然对iwalk 很好。)

    2. 我倾向于在这样的块中使用which,因为没有which 的否定可能是有问题的(负空向量不会做“无”)。相反,我建议使用逻辑向量,而不是整数向量。

      示例:我将尝试一个愚蠢的 1 %in% 2 条件,它显然应该什么也找不到(如果你的否定,返回所有行):

      dge[[1]][ -which(1 %in% 2), ]
      #  [1] mpg  cyl  disp hp   drat wt   qsec vs   am   gear carb
      # <0 rows> (or 0-length row.names)
      

      使用逻辑向量代替(和!而不是-)返回我们期望的(即所有行):

      dge[[1]][ !(1 %in% 2), ]
      #                    mpg cyl disp  hp drat    wt  qsec vs am gear carb
      # Mazda RX4         21.0   6  160 110 3.90 2.620 16.46  0  1    4    4
      # Mazda RX4 Wag     21.0   6  160 110 3.90 2.875 17.02  0  1    4    4
      # Datsun 710        22.8   4  108  93 3.85 2.320 18.61  1  1    4    1
      # Hornet 4 Drive    21.4   6  258 110 3.08 3.215 19.44  1  0    3    1
      # Hornet Sportabout 18.7   8  360 175 3.15 3.440 17.02  0  0    3    2
      

    【讨论】:

      【解决方案3】:

      一个选项是filter

      library(tidyverse)
      map(DGE_tables, ~ .x %>% 
                        filter(column1 != "to_delete"))
      #[[1]]
      #  column1 column2
      #1 to_keep      45
      
      #[[2]]
      #  column1 column2
      #1 to_keep      27
      

      slice

      map(DGE_tables, ~ .x %>% 
                        slice(which(column1 != "to_delete")))
      

      或者也可以使用base R 完成

      lapply(DGE_tables, subset, subset = column1 != "to_delete")
      

      注意:OP 的数据集是 data.framelist 并且需要返回输出 listdata.frames 和行的子集

      它不适用于keepdiscard

      purrr::keep(DGE_tables, ~ .x[['column1']] == 'to keep')
      

      错误:谓词函数必须返回单个 TRUEFALSE,而不是 长度为 2 的逻辑向量

      数据

      DGE_tables <- list(structure(list(column1 = c("to_delete", "to_keep"), 
         column2 = c(56L, 
      45L)), class = "data.frame", row.names = c("1", "2")), structure(list(
          column1 = c("to_delete", "to_keep"), column2 = c(78L, 27L
          )), class = "data.frame", row.names = c("1", "2")))
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-12-22
        • 1970-01-01
        • 1970-01-01
        • 2023-04-10
        • 1970-01-01
        • 1970-01-01
        • 2014-05-26
        • 1970-01-01
        相关资源
        最近更新 更多