我有一个列有很多零值和偶尔的十进制值,例如
c <- c(0,0,0,0.0927,0,0,0.100821,0)
我有一个单独的列v
,其中包含所有十进制数字:
v <- c(0.091,0.0981,0.101,0.102,0.092,0.1,0.091,0.099)
如果c
中的值> 0,我想从该观察结果(即从该行向下)查看列v
,看看是否,在该范围内的任何位置,有一个值低于c
的行/观察中的特定值。理想情况下,我想返回较低数字的第一个实例的值和/或行号/索引。
输出如下所示: (NA,NA,NA,5,NA,NA,8,NA)
即。输出返回v中下一个实例的v中的行号,该值小于C中的相应数字。它忽略v,.091中的第一个值,即使它低于C(.0927)中的第一个数字,因为它发生在C之前(数据按时间顺序排列)。我只想查看后续行。
我真的非常感谢任何帮助。 :-) w ^
答案 0 :(得分:1)
假设可以有多个符合条件的值(即v
中的多个元素低于c
中的正值
positiveMatches <- which(c > 0) #Find the positive values in c
resultList <- list() #Set up a vector to store our data frames
#Loop through each positive match
for(i in positiveMatches){
elementName <- paste0(i, "_", c[i]) #Name the list element after the index and value in c
restrictedV <- c(rep(FALSE, i-1), rep(TRUE, length(v)-(i-1)))
lowerMatches <- (v[i:length(v)] < c[i]) & restrictedV #Find the index of those elements in v which are less than our positive match in c
resultList[[elementName]] <- data.frame(index = which(lowerMatches),
value = v[lowerMatches]
)
}
这应该给你一个数据帧列表,其中每个元素以c中的索引和值命名,并且数据帧在v中包含每个合适元素1行,提供v中每个元素的索引和值比c中的那个。
这里唯一的技巧是计算我们的值为真的索引。我使用which
命令执行此操作以获取c中的索引。一旦我拥有了这些值,我就可以循环遍历它们,并计算出适用于每个c的索引,我用lowerMatches <- v < c[i]
做了这个。一旦我获得了所有信息,我就必须将它们绑定到一个数据帧中。
你没有给出你希望输出结果的例子,所以我提出了一些我认为会很好的东西。您可能希望修改此代码以将c的索引和值存储为除列表元素名称之外的其他内容。
您可以使用names(resultList)
来获取这些内容,但此时您应该尝试修改代码以将这些值存储在更有用的位置。
编辑:我意识到我错过了“从这一点向下”部分,所以我在restrictedV
中添加了一个额外的检查,它只生成一个允许的所有值的索引。如果您不希望它包含与c中相同的行(即忽略索引5),只需将i-1
更改为i
检查中的restrictedV
。
答案 1 :(得分:1)
我不完全确定逻辑,但这会重现您的预期结果并且很短(仅限基础R)。
sapply(seq_along(c), function(i) {
idx <- which(v < c[i]);
if (length(idx) > 0) return(min(idx[idx > i])) else return(NA);
})
#[1] NA NA NA 5 NA NA 8 NA
c <- c(0,0,0,0.0927,0,0,0.100821,0)
v <- c(0.091,0.0981,0.101,0.102,0.092,0.1,0.091,0.099)
答案 2 :(得分:0)
我认为这可以满足您的需求吗?此方法定义要应用于数据的每一行的自定义函数,然后使用purrr::pmap
将函数应用于每一行并生成一个向量。然后,您可以将矢量绑定为数据的新列。这避免了for
循环,但这是否值得,这是值得怀疑的。如果NA
不为正,则结果为c
的新列;如果小于v
则为最低的行索引;如果不是{&1},则为0
39;吨
您给出的示例没有可能出现的两种情况。每次c
为正数时,v
大于后来的值,因此0
永远不会返回此处。此外,v
中可以有相同的值,这使得&#34;的索引定义为最小值&#34;暧昧。这也可能是一种更简单的方法。
编辑:我看到示例数据已更改,您实际上是在寻找第一个较低的值,而不是最小值。如果你不先修改这个答案,请尝试回到这个并修复它!
library(tidyverse, quietly = TRUE)
v <- c(0.09199,0.0981,0.101,0.10002,0.0927273,0.1,0.091,0.099,0.105,0.1,0.1,0.1,0.1,0.100821,0.09)
c <- c(0,0,0,0,0.0927273,0,0,0,0,0,0,0,0,0.100821,0)
tbl <- tibble(c, v) %>% rowid_to_column()
is_v_lower <- function(rowid, c, v){
if (c <= 0){
return(NA)
} else if (v > min(tbl$v[(rowid + 1):nrow(tbl)])) {
min_index = which.min(tbl$v[(rowid + 1):nrow(tbl)])
later_rowid = tbl$rowid[(rowid + 1):nrow(tbl)]
return(later_rowid[min_index])
} else {
return(0)
}
}
output <- pmap_chr(tbl, is_v_lower)
new_tbl <- bind_cols(tbl, lower_v_index = output) %>% print()
#> # A tibble: 15 x 4
#> rowid c v lower_v_index
#> <int> <dbl> <dbl> <chr>
#> 1 1 0 0.0920 <NA>
#> 2 2 0 0.0981 <NA>
#> 3 3 0 0.101 <NA>
#> 4 4 0 0.100 <NA>
#> 5 5 0.0927 0.0927 15
#> 6 6 0 0.100 <NA>
#> 7 7 0 0.0910 <NA>
#> 8 8 0 0.0990 <NA>
#> 9 9 0 0.105 <NA>
#> 10 10 0 0.100 <NA>
#> 11 11 0 0.100 <NA>
#> 12 12 0 0.100 <NA>
#> 13 13 0 0.100 <NA>
#> 14 14 0.101 0.101 15
#> 15 15 0 0.0900 <NA>
答案 3 :(得分:0)
使用&#34; tidyverse&#34;定义tibbles(data.frames)和%>%
运算符(管道;请参阅magrittr包中的?"%>%"
)。
library(tidyverse)
对于任何组和向量x和y,我认为你的标准是(根据需要进行调整......)
f = function(x, y) { y[1] = x[1]; which.max(y < y[1]) }
使用行索引列i
从原始数据创建一个tibble。根据{{1}}
c
总结tbl,提取每组中的相关信息
tbl = tibble(i = seq_along(c), c, v) %>% group_by(grp = cumsum(c != 0))
将原始表格加入答案并清理
ans = summarize(tbl, i = i[1], idx = i[1] + f(c, v) - 1L)
也许在> left_join(tbl, ans) %>% ungroup() %>% select(-i, -grp)
Joining, by = c("i", "grp")
# A tibble: 8 x 3
c v idx
<dbl> <dbl> <int>
1 0 0.0910 1
2 0 0.0981 NA
3 0 0.101 NA
4 0.0927 0.102 5
5 0 0.0920 NA
6 0 0.100 NA
7 0.101 0.0910 8
8 0 0.0990 NA
中放置更多逻辑,例如
f()
当例如在v中的值不小于c时尝试确定结果时,这将有所帮助。