【问题标题】:How to write a function to count the number of observations based on specific conditions in R?如何编写一个函数来根据R中的特定条件计算观察次数?
【发布时间】:2019-12-07 17:58:15
【问题描述】:

我有一个包含 16 个变量的 1401 个观测值的数据框。对于每一列(第一列除外),我有 1(如果满足条件)或 0(如果不满足条件)。总的来说,这个想法是计算有多少观察连续满足某些条件。我们可以把它想象成一棵决策树:在第一个分支中,你可以有 1(条件满足)或 0(条件不满足),在第二个分支中,从第一个分支的 0 开始,你也可以有1 或 0 等...在我的数据框中,分支是列。我想调查以不同顺序查看不同分支(列)的影响。 如果我知道 Cn-1 列中有“0”,我的想法是计算 Cn 列中“1”的数量。

dput(droplevels(head(data,20)))
structure(list(Substance = structure(c(13L, 9L, 10L, 12L, 1L, 
19L, 16L, 17L, 5L, 2L, 14L, 7L, 4L, 6L, 20L, 18L, 15L, 3L, 11L, 
8L), .Label = c("104653-34-1", "107-02-8", "111-30-8", "12057-74-8", 
"122454-29-9", "14915-37-8", "20859-73-8", "27083-27-8", "28772-56-7", 
"3691-35-8", "55965-84-9", "56073-07-5", "56073-10-0", "5836-29-3", 
"71751-41-2", "74-90-8", "81-81-2", "86347-14-0", "90035-08-8", 
"91465-08-6"), class = "factor"), colA = c(1L, 1L, 1L, 1L, 1L, 
1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L), 
    colB = c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
    1L, 1L, 1L, 0L, 0L, 0L, 0L, 0L), colC = c(1L, 1L, 1L, 
    1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
    1L, 1L), colD = c(0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 1L, 0L, 
    0L, 0L, 0L, 0L, 0L, 0L, 1L, 1L, 0L), colE = c(0L, 0L, 0L, 
    0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 1L, 0L, 0L, 0L, 0L, 
    1L, 1L), colF = c(0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 
    0L, 0L, 0L, 0L, 0L, 0L, 1L, 0L, 0L), colG = c(0L, 0L, 0L, 0L, 
    0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 1L, 1L, 
    1L), colH = c(0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 
    0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L), colI = c(0L, 0L, 0L, 0L, 0L, 
    0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 1L
    ), colK = c(1L, 1L, 1L, 1L, 1L, 1L, 0L, 1L, 0L, 0L, 1L, 0L, 
    0L, 1L, 0L, 0L, 1L, 0L, 0L, 0L), colJ = c(0L, 0L, 0L, 
    0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 1L, 0L, 1L, 0L, 1L, 
    0L, 0L), colL = c(1L, 1L, 1L, 1L, 1L, 1L, 0L, 1L, 1L, 
    0L, 1L, 0L, 0L, 1L, 0L, 1L, 1L, 0L, 0L, 1L), colM = c(NA_integer_, 
    NA_integer_, NA_integer_, NA_integer_, NA_integer_, NA_integer_, 
    NA_integer_, NA_integer_, NA_integer_, NA_integer_, NA_integer_, 
    NA_integer_, NA_integer_, NA_integer_, NA_integer_, NA_integer_, 
    NA_integer_, NA_integer_, NA_integer_, NA_integer_), colN = c(1L, 
    1L, 1L, 1L, 1L, 1L, 1L, 0L, 1L, 1L, 0L, 1L, 1L, 1L, 1L, 1L, 
    1L, 1L, 1L, 1L), colO = c(1L, 1L, 1L, 1L, 1L, 1L, 
    1L, 1L, 1L, 1L, 1L, 0L, 0L, 1L, 1L, 1L, 1L, 1L, 1L, 1L)), .Names = c("Substance", 
"Oral", "Dermal", "Inhalation", "SC", "SED", "RS", "SS", "M", 
"C", "R", "STOT.SE", "STOT.RE", "AT", "Eco.Acute", "Eco.Chronic"
), row.names = c(1L, 2L, 3L, 4L, 5L, 6L, 7L, 9L, 10L, 12L, 13L, 
14L, 17L, 18L, 19L, 20L, 21L, 22L, 28L, 34L), class = "data.frame")
#I define the order in which I look at the columns
orderA <- colnames(data)[2:16]
#no-yes function counts chemicals which meet condition Cn when condition Cn-1 is not met
count_no_yes <- function(data, cols) {
    data <- data[, cols]
    sum(apply(data, 1, function(x) all(x == 1)))
}
endpoints <- 0:15
#scenario A with order A of the columns
counts <- sapply(1:15, function(i) count_no_yes(data, orderA[1:i]))
counts <- c(nrow(data), counts)
scenarioA <- data.frame(endpoint=endpoints, hits=counts, scenario="scenarioA")

我的问题是我不知道如何在我的代码中包含来自先前观察的信息。电流不工作。我收到以下错误:Error in apply(data, 1, function(x) all(x == 1)):dim(X) must have a positive length.

然后的想法是为树的每个分支(列)绘制满足条件的观察数。

#scenario B with a different order of the columns
orderB <- colnames(data)[c(9, 10, 11, 5, 6, 8, 3, 2, 4, 13, 12, 7, 14, 15, 16)]
counts <- sapply(1:15, function(i) count_yes_yes(data, orderB[1:i]))
counts <- c(nrow(data), counts)
scenarioB <- data.frame(endpoint=endpoints, hits=counts, scenario="scenarioB")
#combine the different scenarios and plot
scenarios <- rbind(scenarioA, scenarioB)
library(ggplot2)
ggplot(scenarios, aes(x=endpoint, y=hits, color=scenario, group=scenario)) + 
  geom_point() +
  geom_line()

【问题讨论】:

  • 你能发布一个你预期输出的例子吗?
  • 谢谢@jludewig。我为正在绘制的绘图添加了代码。

标签: r function count


【解决方案1】:

会是这样吗?

我们用tidy::gatherdplyr::group_by(par) 整理数据,并计算 0 后跟 1 的次数。

my.fun <- function(x) {
  #Values
  v <-rle(x)[[2]]
  #Consecutive lenght
  l <- rle(x)[[1]]

  tmp <- data.frame(v = v, l=l)
  tmp <-
    tmp %>% 
    # for each column find a substance with 
    # 1 which came after a substance with value 0
    # and check that 1 is followed by a zero
    mutate(flag = ifelse(v==1 & lag(v)==0 & lead(v) == 0, 1, 0))

  #return the sum of the `flag`value
  sum(tmp$flag, na.rm = TRUE)
}

df %>% 
  tidyr::gather("par", "value", everything(), -Substance) %>% 
  group_by(par) %>% 
  summarise(c = my.fun(value))


    # A tibble: 15 x 2
   par             c
   <chr>       <dbl>
 1 AT              0
 2 C               0
 3 Dermal          0
 4 Eco.Acute       1
 5 Eco.Chronic     0
 6 Inhalation      0
 7 M               0
 8 Oral            0
 9 R               4
10 RS              1
11 SC              2
12 SED             1
13 SS              0
14 STOT.RE         4
15 STOT.SE         3

rle 函数是分析向量中连续性的真正瑰宝。 my.fun 可能可以根据您的具体需求进行调整。

【讨论】:

  • 亲爱的 Kresten,我不确定我是否理解。 “最长连续 1 的长度”是什么意思?
  • 嗨,艾米莉。我的答案提供的是一种计算每种物质连续 1 数量的方法。这是在表被旋转以使其仅包含三列之后完成的。 Substanceparvalue。现在par列包含除Substance之外的所有列名。 my.fun 然后计算每个物质组最长连续的数量。这是你想要的吗?
  • 哦,好的。我明白。我实际上很想知道在前一列和所有列都具有 0 之后,一列具有 1 的物质的数量。我想编写一个函数,以便我可以计算列的各种排名,因为这会改变最终输出。
  • 我已经更新了答案。我仍然不确定它是您想要的每种物质还是每列的计数。只需交换group_by中的参数即可满足您的愿望
猜你喜欢
  • 2021-11-03
  • 1970-01-01
  • 1970-01-01
  • 2012-03-14
  • 1970-01-01
  • 2022-12-08
  • 2018-01-09
  • 2014-07-06
  • 2021-07-16
相关资源
最近更新 更多