如何在存储在列表中的特定文本前面加上减号 [R]
How to put minus in front of specific texts stored in a list [R]
我有如下所示的列表:
name <- c("A","B","C","D","E")
n <- c("1, 2, 3, 4, 5", "6, 7, 8", "9, 10", "11, 12, 13, 14", "15, 16, 17")
type <- c("a", "b", "c", "d", "e")
list <- list(name=name, n=n, type=type)
> list
$name
[1] "A" "B" "C" "D" "E"
$n
[1] "1, 2, 3, 4, 5" "6, 7, 8" "9, 10" "11, 12, 13, 14" "15, 16, 17"
$type
[1] "a" "b" "c" "d" "e"
- 列表有三个变量,分别命名为
name
、n
和type
- 每个元素一一对应(即
name=A
的type
是a
),因此每个元素的向量个数相同 n
存储一系列整数,这些整数存储在由comma (,)
分割的字符串中(即name=A
的n
是1, 2, 3, 4, 5
)n
可能有不同数量的整数
另一方面,我有另一个数据框:
df <- data.frame(
name=c("A","A","A","A","A","B","B","B","C","C","D","D","D","D","E","E","E"),
n=c(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17),
yn=c("Yes","Yes","No","No","Yes","No","Yes","Yes","Yes","Yes","No","Yes","Yes","No","Yes","Yes","Yes"))
> df
name n yn
1 A 1 Yes
2 A 2 Yes
3 A 3 No
4 A 4 No
5 A 5 Yes
6 B 6 No
7 B 7 Yes
8 B 8 Yes
9 C 9 Yes
10 C 10 Yes
11 D 11 No
12 D 12 Yes
13 D 13 Yes
14 D 14 No
15 E 15 Yes
16 E 16 Yes
17 E 17 Yes
- 数据框有一个
n
的列表,对应列表中的name
和n
- 此外,这个数据框还有一个属性
yn
,定义节点是yes
还是no
如果数据框中对应的yn
是No
,我想把minus (-)
放在list
中存储的整数前面,如下所示:
有谁能实现这个操作吗? 这看起来有点奇怪,但我需要保留列表的结构。
非常感谢您的建议!!
基数 R:
sf <- function(y, x){
z <- df$yn[which(df$n %in% as.numeric(y) & df$name == list$name[x])]
y[which(z == "No")] <- paste0("-",y[which(z == "No")])
return(y)
}
> list$n <- sapply(seq_along(list$n), function(x) {gsub(" -", "-", paste(sapply(strsplit(list$n[x], split = ", "), sf, x), collapse = ", "))})
> list
$name
[1] "A" "B" "C" "D" "E"
$n
[1] "1, 2,-3,-4, 5" "-6, 7, 8" "9, 10" "-11, 12, 13,-14" "15, 16, 17"
$type
[1] "a" "b" "c" "d" "e"
您可以试试下面的代码
list2DF(lst) %>%
separate_rows(n, convert = TRUE) %>%
left_join(df) %>%
mutate(n = n * (2 * (yn == "Yes") - 1)) %>%
group_by(name, type) %>%
summarise(n = toString(n)) %>%
ungroup() %>%
as.list()
这给出了
$name
[1] "A" "B" "C" "D" "E"
$type
[1] "a" "b" "c" "d" "e"
$n
[1] "1, 2, -3, -4, 5" "-6, 7, 8" "9, 10" "-11, 12, 13, -14"
[5] "15, 16, 17"
将数据放入dataframe,乘以yn
的值,再次得到列表格式的数据。
library(dplyr)
library(tidyr)
bind_rows(list) %>%
separate_rows(n, sep = ',\s*', convert = TRUE) %>%
left_join(df, by = c('name', 'n')) %>%
mutate(n = n * ifelse(yn == 'No', -1, 1)) %>%
group_by(name, type) %>%
summarise(n = toString(n), .groups = 'drop') %>%
as.list()
#$name
#[1] "A" "B" "C" "D" "E"
#$type
#[1] "a" "b" "c" "d" "e"
#$n
#[1] "1, 2, -3, -4, 5" "-6, 7, 8" "9, 10" "-11, 12, 13, -14" "15, 16, 17"