我有一個資料框,我想根據資料框的給定行和列中的值對其進行分組
my_data <- data.frame(matrix(ncol = 3, nrow = 4))
colnames(my_data) <- c('Position', 'Group', 'Data')
my_data[,1] <- c('A1','B1','C1','D1')
my_data[,3] <- c(1,2,3,4)
grps <- list(c('A1','B1'),
c('C1','D1'))
grp.names = c("Control", "Exp1", "EMPTY")
my_data$Group <- case_when(
my_data$Position %in% grps[[1]] ~ grp.names[1],
my_data$Position %in% grps[[2]] ~ grp.names[2]
)
或者
my_data$Group <- with(my_data, ifelse(Position %in% grps[[1]], grp.names[1],
ifelse(Position %in% grps[[2]], grp.names[2],
grp.names[3])))
這些示例作業并生成帶有適當標簽的 Group 列,但是我需要在grps串列長度從 1 到大約 25 之間具有靈活性。
我看不到迭代case_with或回圈ifelse的方法,for例如。
my_data$Group <- for (i in 1:length(grps)){
case_when(
my_data$Well %in% grps[[i]] ~ grp.names[i])
}
此示例只是洗掉了 Group 列
grps處理可變長度的最合適方法是什么?
uj5u.com熱心網友回復:
我相信您的問題暗示該grps變數是一個串列,并且該串列中的每個元素本身就是一個陣列,其中包含屬于該組的所有位置。
具體來說,在下面的grps變數中,如果 Position 是“A1”或“B1”,則它屬于您的第一個條目grp.names。同樣,如果位置是“C1”或“D1”,它屬于您的第二個條目所在的位置grp.names
> grps
[[1]]
[1] "A1" "B1"
[[2]]
[1] "C1" "D1"
假設是這種情況,您可以執行以下操作:
matching_group_df <- sapply(grps, function(x){ my_data$Position %in% x})
selected_group <- apply(matching_group_df, 1, function(x){which(x == TRUE)})
my_data$Group <- grp.names[selected_group]
Position Group Data
1 A1 Control 1
2 B1 Control 2
3 C1 Exp1 3
4 D1 Exp1 4
它的作業方式如下:
matching_group_df是一個 True/False 矩陣(通過sapply函式創建),指定該位置所屬的組索引:
> matching_group_df
[,1] [,2]
[1,] TRUE FALSE
[2,] TRUE FALSE
[3,] FALSE TRUE
[4,] FALSE TRUE
TRUE然后,您可以使用 apply 命令逐行選擇具有值的列:
selected_group <- apply(matching_group_df, 1, function(x){which(x == TRUE)})
> selected_group
[1] 1 1 2 2
- 最后,您將這些索引傳遞給您的 grp.names 串列以選擇適當的索引并將它們設定到您的原始資料框中。
grp.names[selected_group]
[1] "Control" "Control" "Exp1" "Exp1"
如果這對您很重要,這也具有僅使用基本 R 函式的小好處。
uj5u.com熱心網友回復:
方法一:哈希表
我會在這里選擇一種不同的方法,因為組構成可能會在分析程序中發生變化,特別是鍵值對的查找表,并撰寫一個小的訪問器函式。
library(tidyverse)
# First, a small adjustment to `grps` to reflect an empty group.
grps <- list(c('A1','B1'),
c('C1','D1'),
NULL)
names <- unlist(grps, use.names = F)
values <- rep(grp.names, map_dbl(grps, length))
h = as.list(values) %>%
set_names(names) %>%
list2env()
# find x in h
f <- Vectorize(function(x) h[[x]], c("x")) # scoping here
這需要一些時間來設定,但使用起來非常方便:
my_data %>%
mutate(Groups = f(Position))
Position Group Data
1 A1 Control 1
2 B1 Control 2
3 C1 Exp1 3
4 D1 Exp1 4
這避免了在多個地方更改代碼,并且可以采用任意長度的組。
方法二:動態切換
或者,我們可以制作任意長度的switch運算式,從組名及其唯一值構建它。
constructor <- function(ids, names){
purrr::imap_chr(as.character(ids), ~paste(paste0("\"", .x ,"\""),
paste0("\"", names[.y], "\""),
sep = "=")) %>%
paste0(collapse = ", ") %>%
paste0("Vectorize(function(x) switch(as.character(x), ", ., ", NA))", collapse = "") %>%
str2expression()
}
my_data %>%
mutate(Group = eval(constructor(names, values)))
在這種情況下,它將評估運算式
expression(Vectorize(function(x) switch(as.character(x), A1 = "Control",
B1 = "Control", C1 = "Exp1", D1 = "Exp1",
NA)))
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/421746.html
標籤:
上一篇:我的代碼永遠不會進入if陳述句的主體,因為條件永遠不會有效。如何成功比較字符?
下一篇:if陳述句回傳[[:未找到
