R:对 data.frame 进行分组和扩展,以仅包含列中可能的名称对

R: grouping and expanding the data.frame to include only possible pairs of names in a column

提问人:Purrsia 提问时间:7/14/2023 更新时间:7/14/2023 访问量:46

问:

我的目标是将我的 data.frame 包含在 R 中列的可能组合(但不是所有可能的组合)中。 类似于命令,但该函数为您提供所有可能的组合,而不仅仅是存在的内容。expandRexpand.grid

首先,我需要按第 1 列中的每个因素进行分组,并保留第 2 列中包含的信息。在第 3 列中,我有“动物”名称的字符串。我想逐行找到此列中出现的每个可能的对(但不是所有可能的对)。例如,如果我在前两行中有“Dreadwing”和“Scorcher”,那将是一对:Dreadwing-Scorcher,它不应该包括 Scorcher-Dreadwing。但是,如果第 4 行和第 5 行是霸王龙和霸王龙,则这对组合应该出现一次:霸王龙-霸王龙,因为霸王龙出现在“动物”列的 2 个单独的行中。如果霸王龙出现在 3 个单独的行中,那么这对应该出现 3 次,依此类推。

最后,对应将 data.frame 扩展 2 列以存储对。换句话说,Dreadwing 和 Scorcher 对应该各自在自己的单独列中,但在同一行中。

我手动将这张图片放在一起,以显示我拥有的 data.frame 的输出应该是什么(注意:Area_1 和 Area_2 分开只是为了将结果放在一个屏幕截图中)。左边:我在第一行 Dreadwing 上放置了显示所需组合的箭头。右边:所有Area_1和Area_2的预期结果。

enter image description here

对于所需的结果,对于Area_1,Dreadwing-Dreadwing 对不应出现,因为 Dreadwing 不会出现在Area_1的任何其他行中。但是,霸王龙出现在 2 个单独的行中,因此应该有霸王龙的组合,以及每排霸王龙与每一行水翼组合的组合。所以,4 个霸王龙-水翼组合。

可重现的数据

创建 data.frame

v <- c(rep("Area_1", 7), rep("Area_2", 7))
w <- c(rep("Forest", 7), rep("Cave", 7))
y <- c("Waterwing", "Scorcher", "Snapmaw", "T-Rex", "T-Rex", "Dreadwing", 
"Waterwing", "Snake", "T-Rex", "T-Rex", "Dreadwing", "Snapmaw", "Scorcher", 
"Waterwing")

stack_df <- data.frame(Area = v, Location = w, Animals = y)
stack_df <- stack_df[order(stack_df$Area, stack_df$Location, stack_df$Animals), ]
row.names(stack_df) <- 1:nrow(stack_df)

使用 tidyR 指南,我发现该命令与命令(仅保留数据中出现的组合)不起作用。例如:expandnesting

library(tidyr)    
stack_df %>%
    dplyr::group_by(Area) %>%
    expand(nesting(Location, Animals, Animals))

将仅返回 11/14 行。

我尝试了多种使用 and 命令的方法。但是,与命令一样,这些命令为您提供了所有可能的组合。expandcrossingexpand.grid

尽管如此,使用命令是我最接近目标的方法。expand

stack_df %>%
dplyr::group_by(Area) %>%
expand(Location, Animals, Animals)

如您所见,所有可能性都包括在内,这不是理想的结果。

关于如何完成这项工作的任何想法?

R DataFrame 嵌套 组合展开

评论


答:

1赞 Gregor Thomas 7/14/2023 #1

在我看来,这听起来/看起来就像您想找到动物对的所有组合(在区域/位置组中),其中对中的第一种动物出现在对中的第二只动物之前的一行中。

我们可以通过添加行号索引并对行号进行不等式约束的自联接来做到这一点。(这需要版本 >= 1.1.0)dplyr

library(dplyr)
stack_df = stack_df |>
  mutate(group_i = row_number(), .by = c(Area, Location))

stack_df |>
  inner_join(
    stack_df,
    by = join_by(Area, Location, group_i < group_i),
    suffix = c("..2", "..3")  
  ) |>
  select(-starts_with("group_"))
#      Area Location Animals..2 Animals..3
# 1  Area_1   Forest  Dreadwing   Scorcher
# 2  Area_1   Forest  Dreadwing    Snapmaw
# 3  Area_1   Forest  Dreadwing      T-Rex
# 4  Area_1   Forest  Dreadwing      T-Rex
# 5  Area_1   Forest  Dreadwing  Waterwing
# 6  Area_1   Forest  Dreadwing  Waterwing
# 7  Area_1   Forest   Scorcher    Snapmaw
# 8  Area_1   Forest   Scorcher      T-Rex
# 9  Area_1   Forest   Scorcher      T-Rex
# 10 Area_1   Forest   Scorcher  Waterwing
# 11 Area_1   Forest   Scorcher  Waterwing
# 12 Area_1   Forest    Snapmaw      T-Rex
# 13 Area_1   Forest    Snapmaw      T-Rex
# 14 Area_1   Forest    Snapmaw  Waterwing
# 15 Area_1   Forest    Snapmaw  Waterwing
# 16 Area_1   Forest      T-Rex      T-Rex
# 17 Area_1   Forest      T-Rex  Waterwing
# 18 Area_1   Forest      T-Rex  Waterwing
# 19 Area_1   Forest      T-Rex  Waterwing
# 20 Area_1   Forest      T-Rex  Waterwing
# 21 Area_1   Forest  Waterwing  Waterwing
# 22 Area_2     Cave  Dreadwing   Scorcher
# 23 Area_2     Cave  Dreadwing      Snake
# 24 Area_2     Cave  Dreadwing    Snapmaw
# 25 Area_2     Cave  Dreadwing      T-Rex
# 26 Area_2     Cave  Dreadwing      T-Rex
# 27 Area_2     Cave  Dreadwing  Waterwing
# 28 Area_2     Cave   Scorcher      Snake
# 29 Area_2     Cave   Scorcher    Snapmaw
# 30 Area_2     Cave   Scorcher      T-Rex
# 31 Area_2     Cave   Scorcher      T-Rex
# 32 Area_2     Cave   Scorcher  Waterwing
# 33 Area_2     Cave      Snake    Snapmaw
# 34 Area_2     Cave      Snake      T-Rex
# 35 Area_2     Cave      Snake      T-Rex
# 36 Area_2     Cave      Snake  Waterwing
# 37 Area_2     Cave    Snapmaw      T-Rex
# 38 Area_2     Cave    Snapmaw      T-Rex
# 39 Area_2     Cave    Snapmaw  Waterwing
# 40 Area_2     Cave      T-Rex      T-Rex
# 41 Area_2     Cave      T-Rex  Waterwing
# 42 Area_2     Cave      T-Rex  Waterwing

评论

1赞 Purrsia 7/14/2023
如此优雅的解决方案!这不仅对我的数据非常有效,而且这个答案还用标志跟踪了我的真实数据中的所有附加列。非常感谢。我将此标记为最终答案。suffix = c("..2", "..3")
0赞 Onyambu 7/14/2023 #2

如果你有 R > 4.3,github 上有一个小包,我用它来做多个测试。

# devtools::install_github('oonyambu/SLR')

stack_df %>%
    mutate(Area = paste(Area, Location), z = 1) %>%
    SLR::multiple_tests(z~Animals|Area, ., \(x,y)list(NULL)) %>%
    separate(Area, c('Area', 'Location'), sep = ' ') %>%
    separate(Value, c('Animal1', 'Animal2'), sep = ':')
     Area Location response   Animal1   Animal2
1  Area_1   Forest        z Dreadwing  Scorcher
2  Area_1   Forest        z Dreadwing   Snapmaw
3  Area_1   Forest        z Dreadwing     T-Rex
4  Area_1   Forest        z Dreadwing Waterwing
5  Area_1   Forest        z  Scorcher   Snapmaw
6  Area_1   Forest        z  Scorcher     T-Rex
7  Area_1   Forest        z  Scorcher Waterwing
8  Area_1   Forest        z   Snapmaw     T-Rex
9  Area_1   Forest        z   Snapmaw Waterwing
10 Area_1   Forest        z     T-Rex Waterwing
11 Area_2     Cave        z Dreadwing  Scorcher
12 Area_2     Cave        z Dreadwing     Snake
13 Area_2     Cave        z Dreadwing   Snapmaw
14 Area_2     Cave        z Dreadwing     T-Rex
15 Area_2     Cave        z Dreadwing Waterwing
16 Area_2     Cave        z  Scorcher     Snake
17 Area_2     Cave        z  Scorcher   Snapmaw
18 Area_2     Cave        z  Scorcher     T-Rex
19 Area_2     Cave        z  Scorcher Waterwing
20 Area_2     Cave        z     Snake   Snapmaw
21 Area_2     Cave        z     Snake     T-Rex
22 Area_2     Cave        z     Snake Waterwing
23 Area_2     Cave        z   Snapmaw     T-Rex
24 Area_2     Cave        z   Snapmaw Waterwing
25 Area_2     Cave        z     T-Rex Waterwing

评论

0赞 Purrsia 7/14/2023
感谢您的回答并向我介绍新软件包。我必须牢记它们。然而,我正在寻找的答案是所有现在的组合。此路径省略了我需要的重复 - 例如,Area_1中的 4 个霸王龙-水翼组合。我需要的总行数应该是 42。
1赞 Onyambu 7/14/2023
@Purrsia在这种情况下,您不按区域分组,这意味着您将公式更改为z~Animals
0赞 Purrsia 7/15/2023
明白了!多谢。