【问题标题】:Turning a subset based on multiple parameters into a looping function将基于多个参数的子集变成循环函数
【发布时间】:2022-02-07 13:12:11
【问题描述】:

我有一个包含 3000 多个项目的数据框(每行是一个新项目,第一列中包含 item_id),每个后续列中有 2500 多个属性。

item_id    attribute_1    attribute_2 ... category_1 ... category_2
x3902      1              5               1              0
x1402      2              0               1              1

我能够成功抓取满足给定属性和类别的 10 个项目的随机列表:

subset_of_items = sample(subset(df$item_id, (df$attribute1 == 3 & df$category_2 == 1 )),10)

我需要对 30 多种属性 + 类别的组合重复此操作。所以我希望创建一个函数,将输出循环并保存到一个表中,其中每个表列是满足一组条件的 10 个项目的列表。

这是我所能得到的,但无法成功运行:

df <- read.csv ("data.csv",sep=",")

attribute <- c("attribute_1", "attribute_2", "attribute_3")
value <- c(1, 2, 5)
category <- c("category_1", "category_1", "category_2")

function1 <- function(x, attribute_x, value_x, category_x)
{
  dftemp = subset(x[["item_id"]], (x[[attribute_x]] == value_x & x[[category_x]] == 1 ))
  output <- cbind(output, dftemp)
}

function1(df, attribute, value, category)

蛋糕上的樱桃是将每一列命名为attribute_x

【问题讨论】:

  • 嗨,欢迎来到 SO!你能提供一些数据来处理吗?建议:您可以通过将dput() 的输出添加到您的数据(的子集)来编辑帖子。

标签: r function parameters subset cbind


【解决方案1】:

您可以执行以下操作(这使用 data.table 方法)

  1. 将 df 设置为 data.table
library(data.table)
df <- read.csv("data.csv",sep=",")
setDT(df)
  1. 使用get(),创建一个名为get_subset() 的修改函数,该函数返回满足属性和类别要求的item_id 向量。它 还检查您是否有 size 项目返回,并用 as.character(NA) 填充以确保返回的向量具有长度 = size
get_subset <- function(x, attribute_x, value_x, category_x, size=10)
{
  subset = x[get(attribute_x)==value_x & get(category_x) == 1, .(item_id)] %>% 
    .[sample(1:.N, size=min(size, .N)), item_id]
  if(length(subset)<size) subset=c(subset,rep(as.character(NA),size-length(subset)))
  return(subset)
}
  1. 将您感兴趣的组合放入一个小的 data.table 中
combinations = data.table(
  attribute = c("attribute_1", "attribute_2"),
  value = c(1, 5),
  category = c("category_1", "category_2")
)
  1. 使用lapply,循环遍历组合的行,每次将组合的属性、值和类别值提供给 get_subset 函数
result = lapply(seq(1,nrow(combinations)), function(i) {
    items = data.table(get_subset(
      x=df,
      attribute_x = combinations[i,attribute],
      value_x = combinations[i,value],
      category_x = combinations[i, category],
      size=10))
    setNames(items, combinations[i,attribute])
})

返回一个包含单个列的 data.tables 列表,该列以该贡献的属性命名

  1. 使用 do.call 和 cbind 将它们绑定到单个 data.table 中
result = do.call(cbind, result)

如果这是你原来的df

df = data.table(
  item_id = paste0("x", stringr::str_pad(sample(1:1000,100),width = 4,side = "left",pad = "0")),
  attribute_1=sample(1:10, 100, replace=T),
  attribute_2=sample(1:10, 100, replace=T),
  category_1=sample(c(0,1),100, replace=T),
  category_2=sample(c(0,1),100, replace=T)
)

那么上面的combinations,将在result 中返回类似以下的内容(注意,我的 df 示例使用没有种子的样本,因此您的结果会有所不同)

    attribute_1 attribute_2
 1:       x7511       x7302
 2:       x0325       x0956
 3:       x6748       x1893
 4:       x4462       x6958
 5:       x4146        <NA>
 6:       x5407        <NA>
 7:        <NA>        <NA>
 8:        <NA>        <NA>
 9:        <NA>        <NA>
10:        <NA>        <NA>

【讨论】:

  • 难以置信,这正是我想要完成的。工作就像一个绝对的魅力。谢谢!
猜你喜欢
  • 2013-06-06
  • 2020-06-30
  • 2019-07-05
  • 1970-01-01
  • 2019-10-13
  • 1970-01-01
  • 2016-08-22
  • 2021-10-11
  • 2014-12-04
相关资源
最近更新 更多