Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/r/70.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用dplyr或data.table中的动态列名更改数据_R_Dplyr_Data.table - Fatal编程技术网

使用dplyr或data.table中的动态列名更改数据

使用dplyr或data.table中的动态列名更改数据,r,dplyr,data.table,R,Dplyr,Data.table,我有一个包含许多行和以下列的数据集:一个id列,一组列显示多个值的一轮测量结果(val1.x,val2.x,val3.x,…),另一组列显示相同值的另一轮测量结果(val1.y,val2.y,val3.y,…)。下面是一个简化的工作示例: d <- data.table( id = 1:10, val1.x = c(1, 0, 0, 1, 0, 1, 0, 0, 1, 0), val2.x = c(1, 0, 1, 1, 0, 0, 0, 0, 0, 0), val1.y

我有一个包含许多行和以下列的数据集:一个
id
列,一组列显示多个值的一轮测量结果(
val1.x
val2.x
val3.x
,…),另一组列显示相同值的另一轮测量结果(
val1.y
val2.y
val3.y
,…)。下面是一个简化的工作示例:

d <- data.table(
  id = 1:10,
  val1.x = c(1, 0, 0, 1, 0, 1, 0, 0, 1, 0),
  val2.x = c(1, 0, 1, 1, 0, 0, 0, 0, 0, 0),
  val1.y = c(0, 0, 0, 1, 0, NA, NA, 0, 1, 0),
  val2.y = c(1, 0, 0, NA, 0, 1, 0, 0, 1, 0)
)
从示例中可以明显看出,max是指
max(…,na.rm=T)
。我还有一个变量
cols
已经准备好了这个值:

cols <- c('val1', 'val2')
但我无法让左手边变得充满活力

我还尝试实施基于的解决方案,但它给了我一个错误:

left <- "va1.x"
right <- "va1.y"
new <- "val1.max"
expr <- bquote(.(as.name(new)):=pmax(as.name(left), as.name(right), na.rm=T))
d[, eval(expr)]

leftdata.table
中的一个选项是
melt

library(data.table)
d[melt(d, measure = patterns(cols))[,
    lapply(.SD, max, na.rm = TRUE), .(id), 
    .SDcols = value1:value2], paste0(cols, ".max") :=
         .(value1, value2), on = .(id)][]
#    id val1.x val2.x val1.y val2.y val1.max val2.max
# 1:  1      1      1      0      1        1        1
# 2:  2      0      0      0      0        0        0
# 3:  3      0      1      0      0        0        1
# 4:  4      1      1      1     NA        1        1
# 5:  5      0      0      0      0        0        0
# 6:  6      1      0     NA      1        1        1
# 7:  7      0      0     NA      0        0        0
# 8:  8      0      0      0      0        0        0
# 9:  9      1      0      1      1        1        1
#10: 10      0      0      0      0        0        0

或者另一个没有
melt
ing的选项是基于“cols”中的值对列进行子集,并使用
pmax

d[,  paste0(cols, ".max") := lapply(cols, function(pat)
     do.call(pmax, c(.SD[, grep(paste0('^', pat, '$'), 
           names(.SD)), with =  FALSE], na.rm = TRUE)))]
#    id val1.x val2.x val1.y val2.y val1.max val2.max
# 1:  1      1      1      0      1        1        1
# 2:  2      0      0      0      0        0        0
# 3:  3      0      1      0      0        0        1
# 4:  4      1      1      1     NA        1        1
# 5:  5      0      0      0      0        0        0
# 6:  6      1      0     NA      1        1        1
# 7:  7      0      0     NA      0        0        0
# 8:  8      0      0      0      0        0        0
# 9:  9      1      0      1      1        1        1
#10: 10      0      0      0      0        0        0

或者使用
tidyverse
,使用
pivot\u longer
重塑为“long”,按
max
summary\u中的多列进行分组,并与原始数据集连接

library(dplyr)
library(tidyr)
d %>%
   pivot_longer(cols = -id, names_sep="[.]", names_to = c(".value", "group")) %>% 
   group_by(id) %>%
   summarise_at(vars(starts_with('val')),
     list(max = ~max(., na.rm = TRUE))) %>% 
   left_join(d, .)
#   id val1.x val2.x val1.y val2.y val1_max val2_max
#1   1      1      1      0      1        1        1
#2   2      0      0      0      0        0        0
#3   3      0      1      0      0        0        1
#4   4      1      1      1     NA        1        1
#5   5      0      0      0      0        0        0
#6   6      1      0     NA      1        1        1
#7   7      0      0     NA      0        0        0
#8   8      0      0      0      0        0        0
#9   9      1      0      1      1        1        1
#10 10      0      0      0      0        0        0

这是一个合理的解决方案,但我特别寻找一种使用动态列引用的解决方案。例如,我知道我可以使用类似
d[,(val1.max:=pmax(eval(as.symbol('val1.x'))、eval(as.symbol('val2.x'))的内容使计算的右侧成为动态的
但我无法将左侧设置为动态。因此,请注意,data.table解决方案是对其可以处理的列数进行硬编码(在本例中,仅两列,因为您指定了
value1,value2
)。我试图避免任何硬编码。@Merik我还提供了一个
tidyverse
solutioin@Merik您可以使用
pmax检查我更新的data.table解决方案
此外,我认为grep应该修改为
grep(粘贴0(“^”,pat,“$”),名称(.SD))
因此,如果我们碰巧有其他名称部分匹配的列,那么如果您逐个执行此操作,它们不会被拾取,这不是比
melt
方法更为手动吗
d[,  paste0(cols, ".max") := lapply(cols, function(pat)
     do.call(pmax, c(.SD[, grep(paste0('^', pat, '$'), 
           names(.SD)), with =  FALSE], na.rm = TRUE)))]
#    id val1.x val2.x val1.y val2.y val1.max val2.max
# 1:  1      1      1      0      1        1        1
# 2:  2      0      0      0      0        0        0
# 3:  3      0      1      0      0        0        1
# 4:  4      1      1      1     NA        1        1
# 5:  5      0      0      0      0        0        0
# 6:  6      1      0     NA      1        1        1
# 7:  7      0      0     NA      0        0        0
# 8:  8      0      0      0      0        0        0
# 9:  9      1      0      1      1        1        1
#10: 10      0      0      0      0        0        0
library(dplyr)
library(tidyr)
d %>%
   pivot_longer(cols = -id, names_sep="[.]", names_to = c(".value", "group")) %>% 
   group_by(id) %>%
   summarise_at(vars(starts_with('val')),
     list(max = ~max(., na.rm = TRUE))) %>% 
   left_join(d, .)
#   id val1.x val2.x val1.y val2.y val1_max val2_max
#1   1      1      1      0      1        1        1
#2   2      0      0      0      0        0        0
#3   3      0      1      0      0        0        1
#4   4      1      1      1     NA        1        1
#5   5      0      0      0      0        0        0
#6   6      1      0     NA      1        1        1
#7   7      0      0     NA      0        0        0
#8   8      0      0      0      0        0        0
#9   9      1      0      1      1        1        1
#10 10      0      0      0      0        0        0