【问题标题】:Write files for several column filter为多个列过滤器编写文件
【发布时间】:2020-02-03 13:05:18
【问题描述】:

给定一个 data.frame 和一组列,我想写一个 csv 文件(或一般的文本文件) 对于包含但包含所有列信息的每一列,但是根据相应列过滤的行。

例如,假设我想为每个 Sepal.WidthSepal.Length 保存一个文件,其中包含 top 5分别为每个行:

top_n(iris, 5, Sepal.Width) 
#   Sepal.Length Sepal.Width Petal.Length Petal.Width Species
# 1          5.4         3.9          1.7         0.4  setosa
# 2          5.8         4.0          1.2         0.2  setosa
# 3          5.7         4.4          1.5         0.4  setosa
# 4          5.4         3.9          1.3         0.4  setosa
# 5          5.2         4.1          1.5         0.1  setosa
# 6          5.5         4.2          1.4         0.2  setosa
# this should go in top5_Sepal.Width.csv
top_n(iris, 5, Sepal.Length)
#   Sepal.Length Sepal.Width Petal.Length Petal.Width   Species
# 1          7.7         3.8          6.7         2.2 virginica
# 2          7.7         2.6          6.9         2.3 virginica
# 3          7.7         2.8          6.7         2.0 virginica
# 4          7.9         3.8          6.4         2.0 virginica
# 5          7.7         3.0          6.1         2.3 virginica
# this should go in top5_Sepal.Length.csv

我尝试过类似下面的方法,但是我不知道如何编写 mywrite 函数,即如何访问整个 data.frame 进行过滤(.x 仅包含列)

myvars <- c("Sepal.Width", "Sepal.Length")
tmp <- iris %>%
  map_at(myvars, ~mywrite(.x))

或者,purrr:map2 允许跟踪名称,但不会出现在 _atflavour 中(我想过滤可以在 mywrite 中完成。 但是,再次无法访问整个 iris data.frame:

tmp <- iris %>%
  map2(., colnames(iris), ~mywrite(.x, .y))

作为第三种选择,我认为可以选择循环列名,可能使用整洁的评估,即 mycol &lt;- sym(myvars[i])!!mycol ,但理想情况下希望避免 for 循环。

请注意,这是一个有点愚蠢的玩具示例,仅用于说明问题。

注意 2,this 的答案类似,但基于列中的组而不是单个列:

【问题讨论】:

    标签: r dplyr purrr


    【解决方案1】:

    我们可以使用 map 和非标准评估来获得每个 myvars 的前 5 个值

    library(dplyr)
    purrr::map(myvars, ~top_n(iris, 5, !!sym(.x)))
    
    #[[1]]
    #  Sepal.Length Sepal.Width Petal.Length Petal.Width Species
    #1          5.4         3.9          1.7         0.4  setosa
    #2          5.8         4.0          1.2         0.2  setosa
    #3          5.7         4.4          1.5         0.4  setosa
    #4          5.4         3.9          1.3         0.4  setosa
    #5          5.2         4.1          1.5         0.1  setosa
    #6          5.5         4.2          1.4         0.2  setosa
    
    #[[2]]
    #  Sepal.Length Sepal.Width Petal.Length Petal.Width   Species
    #1          7.7         3.8          6.7         2.2 virginica
    #2          7.7         2.6          6.9         2.3 virginica
    #3          7.7         2.8          6.7         2.0 virginica
    #4          7.9         3.8          6.4         2.0 virginica
    #5          7.7         3.0          6.1         2.3 virginica
    

    如果要将每个部分写入csv,可以将管道扩展到

    map(myvars, ~top_n(iris, 5, !!sym(.x)) %>% write.csv(paste0("top5_", .x, ".csv")))
    

    【讨论】:

    • 这很整洁!没想到那样使用非标准评估,谢谢!唯一可以改进以使其更通用的方法是在管道中使用它,即此后开始 'iris %>% map(..., without referring to iris`,你认为这可能吗?
    • @SebastianMüller 泛型是什么意思?我认为上述解决方案也可以应用于任何数据框?以iris %&gt;% 开头的问题是,它不会返回所有其他列。你可以试试iris %&gt;% select(myvars) %&gt;% map(~top_n(tibble(.x), 5))
    • 对于泛型,我指的是iris %&gt;%.... 解决方案。是的,在这个特定的解决方案中,.x 只包含子集列,所以我想除了.x 之外没有任何变量会包含传递的 data.frame?
    • 我猜这个解决方案目前无法通过iris %&gt;% ... 方法实现。但无论如何你的回答已经足够好了,谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-01-27
    • 2011-03-01
    • 2017-11-19
    • 1970-01-01
    • 1970-01-01
    • 2018-09-15
    • 1970-01-01
    相关资源
    最近更新 更多