【问题标题】:R element by element compute, by groupR逐元素计算,按组
【发布时间】:2019-07-16 03:54:34
【问题描述】:

我正在尝试按 ID 组进行计算。想用dplyr,但不是必须的。在历史列中,我有一串数字(长度相同,36)。我想应用该规则,逐个元素地获取最大(最大值)值,并为每个 Id 获取一个新的单个历史记录。 例如,对于 ID = 1157,新的单个字符串将是 4324000000000000000000000000000000000,因为这些是该 ID 的每个元素的最大值。我想为所有 Id(数以千计)执行此操作。

     Id                              history
1  1157 101000000000000000000000000000000000
2  1157 000000000000000000000000000000000000
3  1157 432100000000000000000000000000000000
4  1157 321000000000000000000000000000000000
5  1157 000400000000000000000000000000000000
6  1157 432100000000000000000000000000000000
7  1157 211000000000000000000000000000000000
26 1351 000000000000000000000000000000000000
27 1351 000000000000000000000000000000000000
45 1351 000000000000000000000000000000000000
46 1351 000000000000000000000000000000000000
47 1351 000000000000000000000000000000000000
48 1351 000000000000000000000000000000000000
49 1351 000000000000000000000000000000000000
50 1351 000000000000000000000000000000000000
51 1351 000000000000000000000000000000000000
52 1351 000000000000000000000000000000000000
53 1351 000000000000000000000000000000000000
54 1351 000000000000000000000000000000000000
55 1351 000000000000000000000000000000000000

【问题讨论】:

  • 这不是每个组的最大值吗? df %>% group_by(Id) %>% slice(which.max(as.numeric(history))) ?
  • 我需要逐个元素,而不是哪一行是最大的。这个例子有点欺骗性。
  • 啊……我明白了。你能用一个更好的例子更新帖子,以便清楚区别吗?如果您能提供dput 的样本数据,也会很有帮助。
  • 你的意思是df %>% group_by(Id) %>% mutate(new_string = max(history))?这会将组中history 列的最大值分配给每个Id 元素

标签: r string dplyr


【解决方案1】:

我们可以拆分每个字符上的每个history 值并创建一个列表列和group_by Id 并使用pmax 来获取每个位置具有最大值的元素。

library(dplyr)
library(purrr)

df %>%
  mutate(new_col = map(history, ~strsplit(., "")[[1L]])) %>%
  group_by(Id) %>%
  summarise(temp = paste0(Reduce(pmax, new_col), collapse = ""))

#  Id    temp                                
# <int> <chr>                               
#1 1157  432400000000000000000000000000000000
#2 1351  000000000000000000000000000000000000

strsplit 创建一个字符列表,因为我们使用的是map,所以它创建了另一个列表,因此输出变成了一个嵌套列表,我们使用[[1L]] 避免了这种情况,所以strsplit 的输出是一个字符向量的列表。

new_col 但是是一个列表列,使用Reduce 我们比较组中的所有new_col 值(Id)并使用pmax 逐个元素地选择具有max 值的元素。

这里要注意的另一件事是我们有 new_col 作为字符向量列表,这意味着 1 是“1”,2 是“2”,依此类推。理想情况下,new_col 应该是用于比较目的的整数向量列表,但在这里我认为这无关紧要,因为我们正在进行逐元素比较,它会产生与普通整数比较相同的结果。测试几个

"2" > "1"
#[1] TRUE
"6" < "1"
#[1] FALSE

在基础 R 中使用相同的逻辑,这将是

stack(lapply(split(strsplit(df$history, ""), df$Id), function(x) 
              paste0(Reduce(pmax, x), collapse = "")))

#                                values  ind
#1 432400000000000000000000000000000000 1157
#2 000000000000000000000000000000000000 1351

数据

df <- structure(list(Id = c(1157L, 1157L, 1157L, 1157L, 1157L, 1157L, 
1157L, 1351L, 1351L, 1351L, 1351L, 1351L, 1351L, 1351L, 1351L, 
1351L, 1351L, 1351L, 1351L, 1351L), history = 
c("101000000000000000000000000000000000", 
"000000000000000000000000000000000000", 
"432100000000000000000000000000000000", 
"321000000000000000000000000000000000", 
"000400000000000000000000000000000000", 
"432100000000000000000000000000000000", 
"211000000000000000000000000000000000", 
"000000000000000000000000000000000000", 
"000000000000000000000000000000000000", 
"000000000000000000000000000000000000", 
 "000000000000000000000000000000000000", 
"000000000000000000000000000000000000", 
"000000000000000000000000000000000000", 
"000000000000000000000000000000000000", 
"000000000000000000000000000000000000", 
"000000000000000000000000000000000000", 
"000000000000000000000000000000000000", 
"000000000000000000000000000000000000", 
"000000000000000000000000000000000000", 
"000000000000000000000000000000000000")), row.names = c("1", 
"2", "3", "4", "5", "6", "7", "26", "27", "45", "46", "47", "48", 
"49", "50", "51", "52", "53", "54", "55"), class = "data.frame")

【讨论】:

  • 那真是太棒了。你能解释一些复杂性吗?具体来说,这个 map(history, ~strsplit(., "")[[1L]])) 和“reduce”。代码运行良好。谢谢你!
  • @ElChapo 添加了一些解释。希望你觉得它有用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-10-22
  • 2020-06-28
相关资源
最近更新 更多