【问题标题】:Apply function to dataframe based on unique values根据唯一值将函数应用于数据框
【发布时间】:2015-02-10 13:23:25
【问题描述】:

我需要将函数应用于数据帧,按唯一值进行子集化或分组。

我的数据如下所示:

FID FIX_NO ELK_ID ALTITUDE     XLOC    YLOC DATE_TIME JulDate
1   NA   5296    393 2260.785 547561.3 4771900        NA     140
2   NA   5297    393 2254.992 547555.9 4771906        NA     140
3   NA   5298    393 2256.078 547563.5 4771901        NA     140
4   NA   5299    393 2247.047 547564.7 4771907        NA     140
5   NA   5300    393 2264.875 547558.3 4771903        NA     140
6   NA   5301    393 2259.496 547554.1 4771925        NA     140
...
24247   NA   4389    527 2204.047 558465.7 4775358        NA     161
24248   NA   4390    527 2279.078 558884.1 4775713        NA     161
24249   NA   4391    527 2270.590 558807.9 4775825        NA     161
24250   NA   4392    527 2265.258 558732.2 4775805        NA     161
24251   NA   4393    527 2238.375 558672.4 4775781        NA     161
24252   NA   4394    527 2250.055 558686.6 4775775        NA     161

我的目标是通过在每个 JulDate 为每个唯一的 ELK_ID 随机选择 4 行来创建一个新的 data.frame。 如果我手动完成,对于每个唯一的 ELK_ID,我的代码如下:

oneelk <- subset(dataset, ELK_ID == 393)
newdata <- do.call(rbind,lapply(split(oneelk,oneelk$JulDate), function(x)x[sample(1:nrow(x),4),]))

>40 个 ELK_ID,所以我需要自动化这个过程。 请帮忙!

【问题讨论】:

  • 使用{}按钮将数据放入代码块中。

标签: r function unique lapply rbind


【解决方案1】:

这是一个 data.table 解决方案。

library(data.table)
setDT(dataset)[,.SD[sample(.N,4)],by=list(ELK_ID,JulDate)]

#    ELK_ID JulDate FID FIX_NO ALTITUDE     XLOC    YLOC DATE_TIME
# 1:    393     140  NA   5297 2254.992 547555.9 4771906        NA
# 2:    393     140  NA   5299 2247.047 547564.7 4771907        NA
# 3:    393     140  NA   5298 2256.078 547563.5 4771901        NA
# 4:    393     140  NA   5300 2264.875 547558.3 4771903        NA
# 5:    527     161  NA   4394 2250.055 558686.6 4775775        NA
# 6:    527     161  NA   4392 2265.258 558732.2 4775805        NA
# 7:    527     161  NA   4390 2279.078 558884.1 4775713        NA
# 8:    527     161  NA   4393 2238.375 558672.4 4775781        NA

注意,这只有在 ELK_IDJulDate 的每个组合至少有 4 行时才有效。

【讨论】:

  • 感谢您的解决方案,不幸的是,看起来我确实有一些 ELK_ID 少于 4 JulDates。
  • 然后使用sample(.N,min(.N,4)) 而不是sample(.N,4)。这将对有多少行进行随机抽样,最多 4 行。
【解决方案2】:

您还可以使用tapply 创建索引,然后只使用子集(假设您的数据集名为df

indx <- unlist(tapply(seq_len(dim(df)[1L]), 
                      df[, c("JulDate", "ELK_ID")], 
                      function(x) sample(x, 4)))
df[indx, ]

【讨论】:

  • 当我定义 indx 时,我得到一个错误,即“参数必须是相同的长度”。我知道对于 ELK_ID 的每个值都有一个对应的 JulDate 值,所以我不确定为什么会出现错误。
  • 您收到此错误的原因是您将数据集转换为data.table 对象(您首先运行了@jihoward 代码)。如果您希望它工作,请在您的原始数据集上运行它
【解决方案3】:

尝试使用两列进行拆分,可能是split(dataset, dataset[, c("ELK_ID", "JulDate")])

【讨论】:

    【解决方案4】:

    还不如添加一个dplyr 解决方案:

    library(dplyr)
    newdf <- yourdata %>%
              group_by(ELK_ID, JulDate) %>%
              sample_n(4)
    

    【讨论】:

    • 我认为这正是我想要的,但我需要管理员批准才能更新我的 R 版本,以便我可以访问 dplyr。会告诉你这件事的进展的!谢谢!
    • library(data.table) 解决方案无需更新我的 R 版本即可工作。感谢您的帮助!
    猜你喜欢
    • 1970-01-01
    • 2021-12-24
    • 1970-01-01
    • 1970-01-01
    • 2021-04-20
    • 1970-01-01
    • 1970-01-01
    • 2020-03-29
    相关资源
    最近更新 更多