【问题标题】:Subset first 500 rows by group, for a subset of groups按组子集前 500 行,用于组子集
【发布时间】:2012-09-10 12:39:53
【问题描述】:

这必须是一个简单的答案。我想对我的数据进行子集化以进行测试。我有一个数据框,我想在其中保留所有信息列,只需减少每个人的观察次数。所以,我有一个唯一标识符和大约 50 个人。我只想选择 2 个人并且我只想从这 2 个人中选择 500 个数据点。

我的数据框名为wloc08。有 50 个唯一 ID。我只选取其中 2 个人,但在这 2 个人中,我只需要每个人的 500 个数据点。

subwloc08=subset(wloc08, subset = ID %in% c("F07001","F07005"))

我可以在此声明中的某处使用[吗?

 reduced= subwloc08$ID[1:500,]

没用。

【问题讨论】:

    标签: r data.table subset


    【解决方案1】:

    如果您只与 2 个人打交道,您可以分别对每个人进行子集化,然后 rbinding 每个子集:

    wloc08F07001 <- wloc08[which(wloc08$ID == "F07001")[1:500], ]
    
    wloc08F07005 <- wloc08[which(wloc08$ID == "F07005")[1:500], ]
    
    reduced <- rbind(wloc08F07001, wloc08F07005)
    

    为了使其更通用,尤其是在处理大量数据时,您可以考虑查看data.table 包。这是一个例子

    library(data.table)
    
    wloc08DT<-as.data.table(wloc08)  # Create data.table
    
    setkey(wloc08DT, "ID")           # Set a key to subset on
    
    # EDIT: A comment from Matthew Dowle pointed out that by = "ID" isn't necessary
    # reduced <- wloc08DT[c("F07001", "F07005"), .SD[1:500], by = "ID"]
    reduced <- wloc08DT[c("F07001", "F07005"), .SD[1:500]]
    

    分解最后一步的语法:

    1. c("F07001", "F07005"):这将通过查找键等于F07001F07005 的所有行来子集您的数据。它还会煽动“by without by”(详见?data.table

    2. .SD[1:500]:这将通过选择 1:500 行来子集 .SD 对象(子集的 data.table)。

    3. EDIT 由于 Matthew Dowle 的更正,此部分已被删除。 “by without by”由第 1 步启动。以前:(by = "ID":这告诉[.data.table 对每个 ID 单独执行第 2 步中的操作,在这种情况下,只有您在第 1 步中指定的 ID。)

    【讨论】:

    • @Kerry,有关更通用的解决方案,请参阅上面的编辑。
    • 这很有趣。我将更多地研究 data.tables。我从来没有遇到过他们。我经常遇到需要跨多个人执行多个命令的情况。
    • @BenBarnes 嗨。所有正确的w.r.t。 .SD 等,除 by="ID" 之外不需要。 j 无论如何都会在 i 中为每个组运行。这对于提高效率很重要。它被称为 by-without-by,或 grouping-by-i。通过包含by="ID",它可以像复合查询一样工作:wloc08DT[c("F07001", "F07005")][, .SD[1:500], by = "ID"],在i 无论如何都连接到ID 的情况下效率较低。
    • 另外,如果有很多组,首先将1:500 保存在诸如.head 之类的变量中可能是值得的,以节省一遍又一遍地创建1:500 向量每个组。
    • @MatthewDowle,感谢您的更正。事实上,我已经从复合查询中构建了语法,却忘记了 by 不是必需的。
    【解决方案2】:

    你可以使用lapply:

    do.call("rbind",
            lapply(c("F07001", "F07005"),
                   function(x) wloc08[which(wloc08$ID == x)[1:500], ]))
    

    您的命令reduced = subwloc08$ID[1:500,] 不起作用,因为subwloc08$ID 是一个向量。但是,reduced = subwloc08$ID[1:500] 会起作用,但会返回 subwloc08$ID 的前 500 个值(而不是 subwloc08 的整行)。

    如果您想对前 30 个主题运行此命令,您可以使用 unique(wloc08$ID)[1:30] 而不是 c("F07001", "F07005")

    do.call("rbind",
            lapply(unique(wloc08$ID)[1:30],
                   function(x) wloc08[which(wloc08$ID == x)[1:500], ]))
    

    【讨论】:

    • 谢谢!有什么办法可以使这更普遍?那么,假设我不想只指定 2 个个体,而是指定 30 个个体,并从每个个体中获取一个子集?我必须输入所有 30 个名字吗?或者我可以做类似 lapply(wloc08[wloc08$ID[1:30]]), function(x).....
    • 如果要对前 30 个主题运行此命令,可以使用 unique(wloc08$ID)[1:30] 代替 c("F07001", "F07005")
    • 酷!我删除了我之前的评论以避免将来混淆。
    • @SvenHohenstein 我尝试了 lapply(unique(wloc08$ID [1:30]),它只返回第一个人的前 500 个位置。
    • 请注意,wloc08$ID[1:30] 之间有一个),但在后者之后没有。
    猜你喜欢
    • 2022-01-01
    • 2023-04-03
    • 1970-01-01
    • 1970-01-01
    • 2023-03-30
    • 1970-01-01
    • 1970-01-01
    • 2016-12-25
    相关资源
    最近更新 更多