【问题标题】:how to subset data using two other dataframes in R如何使用 R 中的其他两个数据框对数据进行子集化
【发布时间】:2020-10-06 06:48:34
【问题描述】:

我有一个 ID 为 (100) 的数据框,每个 ID 的行数不同,所有 ID 的列数都相同。

示例数据框如下所示

a <- data.frame(ID = c(1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2), 
              A = c(12,12.5,15,16,18,20,25,26,29,35, 12,12.5,15,16,18,20,25,26,29,35),
              B = c(20,19,18,17,16,20,25,28,30,35, 20,19,18,17,16,20,25,28,30,35),
              C = c(2,1,5,9,10,11,13,18,25,27,2,1,5,9,10,11,13,18,25,27))

在每个 ID 中,我想对两个指定值之间的数据进行子集化,这两个值分别在另外两个数据帧中。

第一个值是每个ID的第一行,示例数据框如下

 b <- data.frame(ID = c(1,2), 
              A = c(12.0,12.0),
              B = c(20,20),
              C = c(2,2))

第二个值是基于向量中某个值的指定行,示例数据帧如下

c <- data.frame(ID = c(1,2), 
               A = c(25.0,20.0),
               B = c(25,20),
               C = c(13,11))

如果我们可以观察到,每个 ID 对应的行,其值与主数据框 'a' 中的值相同

预期的数据帧如下

d <- data.frame(ID = c(1,1,1,1,1,1,1,2,2,2,2,2,2), 
              A = c(12,12.5,15,16,18,20,25, 12,12.5,15,16,18,20),
              B = c(20,19,18,17,16,20,25, 20,19,18,17,16,20),
              C = c(2,1,5,9,10,11,13,2,1,5,9,10,11))

为了得到预期的输出,我尝试了下面的代码.....但是失败了

for (i in 1:nrow(b)){
Azimuth[i] = (a[which(a$A == b$A[i]):which(a$A == c$A[i])])
}

在这里,我正在尝试使用两个数据帧“b”和“c”来对“a”中的数据进行子集化。但是是否有可能在不使用数据帧'b'的情况下获得相同的输出?!因为在数据框'b'中,每一行都是数据框'a'中每个ID中的第一行

【问题讨论】:

  • 我不明白您想如何对数据进行子集化。但是您可以使用subset() 函数。这可能比你做的更容易:)
  • 我很确定你不能在 [ ] 中使用which()。即使有可能,这也会破坏这一点
  • 对于每个ID,所有ABC 值总是在同一行开始和结束吗?如果不是,当 ID = 1 时,A 从第 1 行开始并在第 5 行结束,而 B 从第 2 行开始并在第 10 行结束时,输出将如何?如果是,那么为什么需要 3 列(A、B 和 C)呢?只需其中 1 个就足够了。
  • 所以基本上你想要这样的东西,对吧? for (i in a$A){ if(between(i, min(b$A), max(c$A))){ print(i) } }
  • 数据框'b'中的行,是数据框'a'中每个ID的第一行......但是数据框'c'中的行可以是该ID的任何行在数据框'a'中。在所有三个数据帧“a”、“b”和“c”中,行值都是相同的。我正在寻找基于数据帧“c”@RonakShah 将上述数据子集到数据帧“a”中每一行的代码

标签: r dataframe data-manipulation


【解决方案1】:

dplyr 解决方案

library(dplyr)
a %>% 
  mutate(end = FALSE) %>% 
  rows_update(c %>% mutate(end = TRUE), by = c("ID", "A", "B", "C")) %>% 
  group_by(ID) %>% 
  slice(1:which(end)) %>% 
  select(-end)

输出:

# A tibble: 13 x 4
# Groups:   ID [2]
      ID     A     B     C
   <dbl> <dbl> <dbl> <dbl>
 1     1  12      20     2
 2     1  12.5    19     1
 3     1  15      18     5
 4     1  16      17     9
 5     1  18      16    10
 6     1  20      20    11
 7     1  25      25    13
 8     2  12      20     2
 9     2  12.5    19     1
10     2  15      18     5
11     2  16      17     9
12     2  18      16    10
13     2  20      20    11

解释:

我猜您想使用一个数据框来对另一个数据框进行子集化,因为您只想在存在 IDABC 的某些组合时才对 a 进行子集化,您在你的数据框c?

如果是这样,您可以通过以下步骤来实现您的目标:

  1. 我们在a 中创建另一个逻辑变量。称它为end,默认为FALSE
  2. 我们还在c 中创建了相同的变量,但将其默认设置为TRUE
  3. 我们使用c 中的end 来更新a 中的end,以更新IDABC 的组合标记的每一行。这样,只有当其他四个变量的ac 完全匹配时,变量end 才会变为TRUE。如果你找不到完全匹配,那么你会得到这个 Error: Attempting to update missing rows.
  4. 对于ID 定义的每个组,我们group_by(ID) 并从第一行中选择直到end TRUE
  5. 您删除该 end 变量,因为它不再有用了。

【讨论】:

  • 根据您的解决方案,我们可以使用数据帧“c”从第一个数据帧中特定 ID 的第一行到该特定 ID 的第 c 个数据帧的行子集数据帧“a”在第一个数据框中。那么,如何进行反向操作,即将数据帧“a”从数据帧“a”中第 c 个数据帧中特定 ID 的行子集到数据帧“a”中特定 ID 的最后一行?
  • @Kumar 将 slice(1:which(end)) 更改为 slice(which(end):n())
  • 在您的解决方案中从顶部开始的第 4 行,我们可以将 'by = c("ID", "A", "B", "C")' 替换为 'by= colnames(a) '....?!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-25
  • 1970-01-01
  • 2021-12-04
  • 2021-03-23
  • 1970-01-01
相关资源
最近更新 更多