【问题标题】:How to create a function which loops through column index numbers in R?如何创建一个循环遍历 R 中的列索引号的函数?
【发布时间】:2019-04-25 16:29:14
【问题描述】:

考虑以下数据框(df):

"id"   "a1"   "b1"   "c1"   "not_relevant"   "p_a1"   "p_b1"   "p_c1"
 a      2      6      0           x             2        19       12
 a      4      2      7           x           3.5         7       11
 b      1      9      4           x             7       1.5        4
 b      7      5      11          x             8        12        5

我想创建一个新列,显示两个对应列之间的乘积之和。为了编写更少的代码,我通过索引号对列进行寻址。不幸的是,我没有编写函数的经验,所以我最终手动编写,这非常繁琐且不是很优雅。

这是一个可重现的数据框示例以及我迄今为止尝试过的示例:

id <- c("a","a","b","b")
df <- data.frame(id)
df$a1 <- as.numeric((c(2,4,1,7)))
df$b1 <- as.numeric((c(6,2,9,5)))
df$c1 <- as.numeric((c(0,7,4,11)))
df$not_relevant <- c("x","x","x","x")
df$p_a1 <- as.numeric((c(2,3.5,7,8)))
df$p_b1 <- as.numeric((c(19,7,1.5,12)))
df$p_c1 <- as.numeric((c(12,11,4,5)))

require(dplyr)

df %>% mutate(total = .[[2]]*.[[6]] + .[[3]] *.[[7]]+ .[[4]] *.[[8]])

这会导致预期的结果,但正如我提到的那样效率不是很高:

"id"   "a1"   "b1"   "c1"   "not_relevant"   "p_a1"   "p_b1"   "p_c1"   "total"
 a      2      6      0           x             2        19       12     118.0
 a      4      2      7           x           3.5         7       11     105.0
 b      1      9      4           x             7       1.5        4      36.5
 b      7      5      11          x             8        12        5     171.0

我正在处理的真实数据有更多的列,所以如果有人能告诉我一种方法来将此操作打包到一个函数中,该函数循环遍历列索引号并将正确的列相互匹配,我会很高兴。

【问题讨论】:

    标签: r function dataframe multiple-columns


    【解决方案1】:

    列索引不是执行此操作的好方法。 (一般来说不是一个好方法......)

    这是一个简单的dplyr 方法,它假定列的对应顺序正确(也就是说,如果"x1", "x2", "x3" 的顺序与"p_x3", "p_x2", "p_x1" 的顺序不同,则会给出错误的结果)。您可能还需要为您的真实数据细化选择标准:

    df$total = rowSums(select(df, starts_with("x")) * select(df, starts_with("p_")))
    df
    #   id x1 x2 x3 not_relevant p_x1 p_x2 p_x3 total
    # 1  a  2  6  0            x  2.0 19.0   12 118.0
    # 2  a  4  2  7            x  3.5  7.0   11 105.0
    # 3  b  1  9  4            x  7.0  1.5    4  36.5
    # 4  b  7  5 11            x  8.0 12.0    5 171.0
    

    另一个不错的选择是将数据转换为长格式,其中有一个 x 列和一个 p 列,其中“索引”列指示 1、2、3。然后操作可以分组完成,最后回到宽格式。

    【讨论】:

    • 非常感谢。不幸的是,我的真实数据的选择标准与我提供的示例不匹配。我将相应地编辑示例。列名应为"a1" "b1" "c1"。但是,列的顺序是正确的。
    • 是的,您可以查看?select_helpers 帮助页面,其中有很多可以在其中完成的示例。对于"a1", "b1", "c1",您可以使用matches("^[a-z]1$"),表示“后跟1 的任何字母”。如果数字不总是 1,那么可能matches("^[a-z][0-9]$") 表示“任何字母后跟任何数字”。
    • 再次感谢您的帮助。解决方案可能是为相应的列添加前缀或后缀。这样,我可以人为地创建一个选择标准。比如像这样:"pre_a1" "pre_b1" "pre_c1"
    • 是的,您只需要一些方法来以编程方式识别列名。
    猜你喜欢
    • 2018-12-24
    • 1970-01-01
    • 1970-01-01
    • 2022-01-08
    • 2013-05-12
    • 2013-03-04
    • 2010-12-09
    • 2021-12-14
    相关资源
    最近更新 更多