【问题标题】:How do I filter data in data frame and change column's cell values based on it using a loop?如何过滤数据框中的数据并使用循环根据它更改列的单元格值?
【发布时间】:2020-05-29 21:03:13
【问题描述】:

目前正在使用具有各种参与者 ID 的更大数据框,如下所示:

#ASC_new Data Frame

           Pcp Choice Target ASC       Product choice_consis
2393 zwyn27soc      B      A   1     USB drive             0
2394 zwyn27soc      B      A   1           job             0
2395 zwyn27soc      B      B   1     USB drive             0
2397 zwyn27soc      B      A   1       printer             0
2399 zwyn27soc      B      B   1 walking shoes             0
2400 zwyn27soc      B      A   1       printer             0

我想尝试遍历每个参与者 (Pcp),并在“选择”列中查看他们的选择。例如,在两个产品“USB 驱动器”下,参与者选择了“B”(选择)。因此,在“choice_consis”下,我希望有一个 1 来代替 0,因为选择是一致的或相等的。虽然,我用于遍历参与者和产品名称的 for 循环不起作用:

#Examples/snippets of my values

pcp_list <- list("ybg606k3l", "yk83d2asc", "yl55v0zhm", "zwyn27soc")
product_list <- list("USB drive", "printer", "walking shoes", "job")

#for loop that isn't working
for (i in pcp_list){ #iterating through participant codes
  for (j in product_list){ #iterating through product names
    comparison <- filter(ASC_new, Pcp == i & Product == j) #filtering participant data and products into new dataframe

    choice_1 <- ASC_new$Choice[1] #creating labels for choice 1 and 2
    choice_2 <- ASC_new$Choice[2]

    if (isTRUE(choice_1 == choice_2)){ #comparing choice 1 and choice 2 and adding value of 1 to Choice_consis column if they are equal

      ASC_new$choice_consis[1] <- 1
      ASC_new$choice_consis[2] <- 1

    } 
  }

}

最后,我想要一个数据框,其中每个参与者的 choice_consis 都标有 1 或 0,表示他们是否在每个产品出现的时候都选择了相同的项目 (A,B,D)。

【问题讨论】:

  • 请使用dput 显示示例,谢谢

标签: r for-loop filter rbind


【解决方案1】:

如果您不关心在不同选择之间崩溃,使用dplyr 是很自然的事情。我将在一个玩具数据框上进行说明:

IDs <- 1:2
choices <- c('A', 'B')
products <- c('USB', 'Printer')
df <- data.frame(Pcp = rep(IDs, each = 4), 
                 Choice = c(rep(choices, each = 2), 
                            rep(choices, each = 2)),
                 Product = c(rep(products, times = 2), 
                             rep(products, each = 2)))

df %>%
  dplyr::group_by(Pcp, Product) %>%
  dplyr::summarize(choice_consis = as.numeric(length(unique(Choice)) == 1))

这(本质上)与您尝试对 for 循环执行的操作相同:查看参与者和产品的每个组合(这就是 group_by 所做的),然后分析该组合(这就是 @ 987654325@ 确实如此)。它比双 for 循环更简洁易读。我会查看Hadley's book on R for Data Science 的第 5 章,以了解有关此类事情的更多信息。

至于你的 for 循环有什么问题,问题是即使你创建了 comparison 数据框,所有后续操作都在 ASC_new 上。因此,如果您想使用 for 循环并维护原始数据的结构,您可以执行以下操作:

for (i in pcp_list) { 
  for (j in product_list) { 

    compare <- (ASC_new$Pcp == i) & (ASC_new$Product == j)
    choices <- ASC_new$Choice[compare]

    if (length(unique(choices)) == 1) {
      ASC_new$choice_consis[compare] <- 1
    } 
  }
}

像您一样创建一个新的数据框会使替换原始数据中的值变得有点困难(因为我们不知道过滤后的数据框来自“哪里”),所以我只获取原始数据的索引对应于参与者-产品组合的框架。另请注意,我消除了只有两个选择的硬编码,以及 if 语句中的isTRUE== 将根据需要评估为TRUEFALSE)。

希望这会有所帮助!

【讨论】:

    【解决方案2】:

    您可以为每个PcpProduct 计算Choice 的唯一值,如果为1,则为1,否则为0。

    这可以在基础 R 中完成:

    df$choice_consis <- +(with(df, ave(Choice, Pcp, Product, FUN = function(x)
                               length(unique(x)))) == 1)
    

    dplyr

    library(dplyr)
    df %>%
      group_by(Pcp, Product) %>%
      mutate(choice_consis = +(n_distinct(Choice) == 1))
    

    data.table

    library(data.table)
    setDT(df)[, choice_consis := as.integer(uniqueN(Choice) == 1), .(Pcp, Product)]
    

    【讨论】:

      猜你喜欢
      • 2018-01-16
      • 2023-02-20
      • 2020-01-18
      • 2021-12-09
      • 1970-01-01
      • 1970-01-01
      • 2017-08-15
      • 2020-07-01
      • 1970-01-01
      相关资源
      最近更新 更多