【问题标题】:How to create a function for subsetting data where the arguments passed to it vary如何为传递给它的参数不同的数据创建一个函数
【发布时间】:2012-03-23 14:02:07
【问题描述】:

这是与my previous post 相关的后续问题。下面是“我想做什么”的更解释性版本,而不是“我如何使这种方法起作用”。

下面是生成“主”数据库的代码,我从中提取元素以进一步用于其他功能。我经常根据组标识号的值提取数据元素。

  • 目标:我希望能够将不同的规范(如输出数据帧的名称和选择的组)“包装”到一个可以调用的函数中。

#####  generating data for example

set.seed(271828)

n.elements <- c(10,10,12,14,16,18)
group.number <- rep(1001:1006, n.elements)
element.id <- c(
    seq(1,n.elements[1], 1),
    seq(1,n.elements[2], 1),
    seq(1,n.elements[3], 1), 
    seq(1,n.elements[4], 1),
    seq(1,n.elements[5], 1),
    seq(1,n.elements[6], 1) ) 

x1 <- round(rnorm(length(group.number),45, 12), digits=0)
x2 <- round(rbeta(length(group.number),2,4), digits = 2)

data.base <- as.data.frame(cbind(group.number, element.id, x1, x2))
data.base

#####  data.base is representative of the large database 


#####  suppose I need to pull a set together made up of groups: 
#####  1003, 1004, and 1001 


groups.set.1 <- as.data.frame(c(1003, 1004, 1001))
bank.names <- c("group.number")
colnames(groups.set.1) <- bank.names
set.sort <- matrix(seq(1,nrow(groups.set.1),1)) 
sort.set.1 <- cbind(groups.set.1, set.sort)

set.1 <- as.data.frame(merge(sort.set.1, data.base, 
by="group.number", all.x=TRUE))

#####  this is how the dataset needs to be ordered for further use
set.1 <- set.1[order(set.1$set.sort, set.1$element.id ), ]
row.names(set.1) <- seq(nrow(set.1))

编辑:假设我想执行相同的任务来生成 set.2,其中 set.2 由以下组组成:1005、1006 和 1002。我可以复制上面的内容代码,并进行相关更改。但是,我想知道是否可以指定一个函数,以便我可以将必要的更改传递给它,并让它根据需要生成输出数据帧。也许有一个名为 group.extract 的函数,我可以在其中指定如下内容:

groups.2 <- c(1005, 1006, 1002)
group.extract(set.2, groups.2)

根据提供的 cmets,列表似乎是可行的方法,并让函数调用列表,其中列表元素可以变化。

【问题讨论】:

  • 看看?assign,它允许您为名称分配值,名称可能从函数中的参数获得。这会让你开始吗?所以就像function(mySet1="set.1")assign(mySet1,42),当然要小心环境。编辑:...如您之前帖子的答案中所述。
  • 我仍然不确定你想要完成什么,但从你用来描述它的词语来看,你似乎可以尝试传递一个列表(其内容可能是一切你想通过)或使用...功能。
  • @gsk3 感谢您的建议。我现在正在处理这个问题,但我认为你的想法是可行的。
  • 示例代码很清楚,但是文字,尤其是标题,混淆了问题;一个新的标题可能是有序的,可能类似于“如何通过编写函数以特定顺序获取数据子集?”
  • @Aaron 问题标题已按要求更新。

标签: r function


【解决方案1】:

我将使用match 编写此函数,如下所示。在这里,我硬编码了输入数据框的列名,用于匹配和排序;这些也可以作为可选输入添加。输出的列顺序与您的略有不同,但也可以轻松更改。

getset <- function(g, d=data.base) {
  d$set.sort <- match(d$group.number, g)
  d <- d[!is.na(d$set.sort),]
  d <- d[order(d$set.sort, d$element.id),]
  rownames(d) <- NULL
  d
}

您几乎可以完全按照您的建议使用它:

> set.1 <- getset(c(1003, 1004, 1001))
> head(set.1)
  group.number element.id x1   x2 set.sort
1         1003          1 60 0.32        1
2         1003          2 28 0.18        1
3         1003          3 42 0.47        1
4         1003          4 43 0.08        1
5         1003          5 45 0.31        1
6         1003          6 27 0.48        1

如果您有多个组要获取,将它们放在一个列表中并使用lapply 将是可行的方法。

> groups <- list(group1=c(1003, 1004, 1001), group2=c(1005,1006,1002))
> sets <- lapply(groups, getset)
> lapply(sets, head)
$group1
  group.number element.id x1   x2 set.sort
1         1003          1 60 0.32        1
2         1003          2 28 0.18        1
3         1003          3 42 0.47        1
4         1003          4 43 0.08        1
5         1003          5 45 0.31        1
6         1003          6 27 0.48        1

$group2
  group.number element.id x1   x2 set.sort
1         1005          1 27 0.20        1
2         1005          2 51 0.48        1
3         1005          3 49 0.43        1
4         1005          4 48 0.20        1
5         1005          5 33 0.37        1
6         1005          6 41 0.50        1

【讨论】:

    【解决方案2】:

    希望审查 SO 中的代码可以治愈看似中度严重的后 SAS 主义案例。我认为这是一种更 R-ish 的方式:

     pick <-  subset(data.base, group.number %in% c(1003, 1004, 1001) )
     idx <- match(pick$group.number,  c(1003, 1004, 1001) ) 
     pick[ order(idx, pick$element.id), ]
     #---------
       group.number element.id x1   x2
    21         1003          1 60 0.32
    22         1003          2 28 0.18
    23         1003          3 42 0.47
    24         1003          4 43 0.08
    25         1003          5 45 0.31
    26         1003          6 27 0.48 
    snipped----
    

    这就是将策略合并到一个函数中:

    grp.ext.srt <- function(dfrm, grpid) { pick <-  dfrm[ group.number %in% grpid , ]
         idx <- match(pick$group.number,  grpid ) ; rownames(pick) <- NULL
         return(pick[ order(idx, pick$element.id), ])
          }
    

    【讨论】:

    • 非常感谢!几年来我一直没有使用 SAS,但我的新工作经常使用它。我绝对是这里的 R 孤独者/拥护者,但我觉得我正在获得追随者......
    猜你喜欢
    • 2019-04-28
    • 2019-10-09
    • 1970-01-01
    • 2011-03-31
    • 2018-08-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多