在数据框中搜索多个字符串,如果有条件则自下而上?

Searching for multiple strings in dataframe, bottom up in if conditional?

我有一个包含多列的数据框,我们称之为 dat1,我需要根据很多条件提取某些列中的字符串。 每个主题有 350 行,我需要在每个主题的特定列中找到特定字符串的最后一个,包含特定名称,例如"green",并从同一行的另一个字符串中取值。

subject   type    value
111       yellow   354
111       green    584
111       yellow   584
111       blue     492
111       green    493
222       blue     459
222       green    583
222       yellow   539
222       blue     392
222       yellow   394

假设我需要每个主题的最后一个值 "green",我该怎么做?

这样做之后,我还需要获取高于最后一个 "green" 的值,最好将它们保存在两个单独的向量中。

last_green    before_last_green
   493          492
   583          459

我曾尝试制作多个 if 语句,同时还按主题分组,但几乎没有成功。我之前也找不到任何这方面的例子。

是否可以从每个主题的底部搜索第一个"green"?或者如何执行此操作?

代码

tidyverse是你的朋友:

library(tidyverse)
d <- structure(list(subject   = c(111L, 111L, 111L, 111L, 111L, 
                                  222L, 222L, 222L, 222L, 222L), 
                    type      = c("yellow", "green", "yellow", "blue", "green",
                                  "blue", "green", "yellow", "blue", "yellow"), 
                    value     = c(354L, 584L, 584L, 492L, 493L, 
                                  459L, 583L, 539L, 392L, 394L)), 
                    row.names = c(NA, -10L), 
                    class = c("tbl_df", "tbl", "data.frame"))

d %>% 
  group_by(subject) %>% 
  filter(type == "green") %>% 
  summarise_all(last)

# A tibble: 2 x 3
#   subject type  value
#     <int> <chr> <int>
# 1     111 green   493
# 2     222 green   583

说明

  • 对于 group_by,您将根据 subject
  • 的唯一值执行以下操作
  • filter 你只查找 type 等于 green
  • 的行
  • summarise你终于select只剩下最后一个条目

回答两个问题:

df=data.frame("subject"=c(rep(111,5),rep(222,5)),
           "type"=c("yellow","green","yellow","blue","green",
                    "blue","green","yellow","blue","yellow"),
           value=c(354,584,584,492,493,459,583,539,392,394),
           stringsAsFactors = FALSE)
   subject   type value
1      111 yellow   354
2      111  green   584
3      111 yellow   584
4      111   blue   492
5      111  green   493
6      222   blue   459
7      222  green   583
8      222 yellow   539
9      222   blue   392
10     222 yellow   394

创建过滤器 df:

filter_=df%>%rownames_to_column()%>%group_by(subject)%>%
  filter(type=="green")%>%slice(n())

last_green=filter_$value
before_last_green=df$value[as.numeric(filter_$rowname)-1]

结果:

> last_green
[1] 493 583
> before_last_green
[1] 492 459

解释:
我们首先创建行名来跟踪每个 subject 最后 green 出现的位置。然后,我们按 subject 分组并按 type 过滤我们用 slice() 取每组的最后一个元素。然后我们 return last_green 中的 value 和具有这些先前样本位置的行的 value - 1(前一个)。

你可以这样做:

library(tidyverse)

dat %>%
  rownames_to_column() %>%
  group_by(subject) %>%
  filter(type == 'green') %>%
  summarise(
    last_green        = last(value), 
    before_last_green = dat$value[as.numeric(last(rowname)) - 1]
    )

这里发生了什么:

  • 您将 data.frame 的行名移动到变量 rowname 中(请参阅后面的原因);
  • 您按 subject 对数据进行分组,以对与特定 subject;
  • 相关的数据子集应用以下操作
  • filter你的数据,只剩下greens;
  • 最后:
    • summarize 你的数据,为每个先前 过滤的 子集获取最后 value,并将其分配给 value_green;
    • 您从环境中借用了整个未转换的 dat,通过对应于 .last(ronwame) - 1 的行从 dat 中子集 value数据,即通过管道进入 summarize 的数据。

计算结果为:

# A tibble: 2 x 3
  subject last_green before_last_green
    <int>      <int>             <int>
1     111        493               492
2     222        583               459

您的数据:

dat <- read.table(
  text = "subject   type    value
111       yellow   354
111       green    584
111       yellow   584
111       blue     492
111       green    493
222       blue     459
222       green    583
222       yellow   539
222       blue     392
222       yellow   394",
  header = T, stringsAsFactors = F
)