首页 > 解决方案 > 根据另一个数据集中指定的值对数据框进行子集化

问题描述

我有一个类似于DataSetA下面创建的数据框。观察代表在每个人的长度上对相同的 3 个变量进行的测量。在个人(A、B、C 等)内,每个观察与前一个观察的距离相等。为了澄清,在真实数据中,每个人的长度是不同的。Var1因此,每个个体内的每个变量 ( , Var2, )的指数数量相同Var3,但每个个体之间的指数数量不同(Individual A可能有 50 个观察值,但Individual B可能有 70 个)。

我有兴趣比较从每个人的不同位置开始的个人之间等长的数据。因此,我凭经验检测每个人体内的单个“兴趣点”(单个索引),并希望收集该点和之前的 9 个点,以便在个人之间进行比较。

我需要以这样的方式对数据进行子集化,最终得到一个新的数据框,其中包含每个人的这十个观察值,格式与原始数据框相同。在过去,我通过 Tidyverse(如下所示)对每个人使用过滤器和切片函数来完成此操作,并使用 rbind 将它们组合到新的数据帧中。然而,这样做需要在我的代码中进行大量的重复(和时间),并且我的数据集正在增长。

我想为每个人创建一个单独的对象,该对象具有一行和两列,其中包含个人 ID 和他们的“兴趣点”的相应索引。基本上我想说; “如果idin 数据集A与 in 数据集匹配,则id数据集中B旁边的数字是我想要ID在数据集中开始B的行的索引(兴趣点),并返回该行和它之前的九行新数据框”。RA

我不确定 for 循环是否是执行此操作的合适方法,或者是否还有其他方法。任何帮助将不胜感激。

Individuals <- rep(c("A","B","C"), each = 50)

Var1 <- rnorm(50)
Var2 <- rnorm(50)
Var3 <- rnorm(50)

DataSetA <- cbind(Individuals, Var1, Var2, Var3)
DataSetA <- data.frame(DataSetA)

#How I usually filter to achieve what I want:
#The point of interest for Individual A is the 32nd observation taken on
#Individual A, so I need observations 23:32
A <-
  DataSetA%>%
  filter(Individuals == A)%>%
  slice(23:32)
#The point of interest for Individual B is the 35th observation taken on
#Individual B, so I need observations 26:35
#note that this is the 35th observation for that individual (not the 35th observation of the data set)
B <-
  DataSetA%>%
  filter(Individuals == B)%>%
  slice(26:35)
#The point of interest for Individual C is the 16th observation taken on
#Individual B, so I need observations 7:16
C <- 
  DataSetA%>%
  filter(Individuals == C)%>%
  slice(7:16)
#I then have to combine them using rbind
ExtractedData <- rbind(A,B,C)

#Below creates what I would like to use as "dataset B" to tell R what number to start filtering at in DataSetA

Individuals <- c("A","B","C")
PointOfInterest <- c(32,35,16)
DataSetB <- data.frame(Individuals, PointOfInterest)

标签: rfunctionloopsfor-loop

解决方案


一种选择是使用map2

library(dplyr)
library(purrr)
map2_df(DataSetB$Individuals, DataSetB$PointOfInterest, ~ 
       DataSetA %>%
           filter(Individuals == .x, row_number() > .y))

如果我们要过滤 9 行,包括 'DatasetB' 中的 'PointOfInterest' 中显示的行

 map2_df(DataSetB$Individuals, DataSetB$PointOfInterest, ~ 
       DataSetA %>%
       group_by(Individuals)%>%
       mutate(rn = row_number()) %>% #just to show the row number
            filter(Individuals == .x, between(row_number(), .y-9, .y)))
#   Individuals        Var1        Var2        Var3 rn
#1            A -0.50715002 -1.63196034  0.24824287 23
#2            A -0.50694324  0.99443347 -0.25148466 24
#3            A  0.26498877  1.59758547 -0.97999740 25
#4            A  0.59168174 -0.67593906  0.58904189 26
#5            A -0.28834071  0.50565228 -1.40489489 27
#6            A -0.52907038  0.86131470 -1.50978892 28
#7            A -0.17986538  0.74555059 -0.42154441 29
#8            A -0.93043770  0.94839988  1.28018362 30
#9            A -2.46745604 -0.27824127 -0.36406006 31
#10           A -0.05040743  1.13697037 -0.85254191 32
#11           B  0.08314367 -0.07045269 -0.02063172 51
#12           B  2.78494703 -0.75031916 -0.90366751 52
#13           B  0.59528232 -0.09401376  2.14675010 53
#14           B  0.07766635  0.41274946  0.52784216 54

推荐阅读