R 在分组df中的组之间复制数据
我对数据进行了分组,其中包含缺失值的块。我使用R 在分组df中的组之间复制数据,r,dplyr,R,Dplyr,我对数据进行了分组,其中包含缺失值的块。我使用dplyr计算每组目标变量的总和。对于和为零的组,我想用前一组中的值替换该组的值。我可以在一个循环中完成这项工作,但由于我的数据位于一个大数据帧中,因此效率极低 下面是一个合成示例: df <- tbl_df(as.data.frame(cbind(c(rep(1, 4), rep(2, 4)), c(abs(rnorm(4)), rep(NA, 4))))) names(df) <
dplyr
计算每组目标变量的总和。对于和为零的组,我想用前一组中的值替换该组的值。我可以在一个循环中完成这项工作,但由于我的数据位于一个大数据帧中,因此效率极低
下面是一个合成示例:
df <- tbl_df(as.data.frame(cbind(c(rep(1, 4), rep(2, 4)),
c(abs(rnorm(4)), rep(NA, 4)))))
names(df) <- c("group", "var")
df <- df %>%
group_by(group) %>%
mutate(total = sum(var, na.rm = TRUE))
在这种情况下,我想将第2组中的var
值替换为第1组中的var
值,并通过检测第2组中的total=0
来实现
我试图提出一个自定义函数,将其输入到执行此操作的do()
,但不知道如何告诉它将当前组中的值替换为其他组中的值。对于上面的示例,我尝试了以下方法,这些方法将始终使用组1中的值进行替换:
CheckDay <- function(x) {
if( all(x$total == 0) ) { x$var <- df[df$group==1, 2] } ; x
}
do(df, CheckDay)
有什么办法可以让它发挥作用吗?有几件事正在进行。首先,您需要确保
df
是一个data.frame
,您的函数CheckDay(x)
既有局部变量x
,您给它赋值df
作为全局变量df
本身,最好将函数中的所有内容都保持为局部变量。最后,您对do(df,CheckDay(.)
的调用缺少(.)
部分。试试这个,这个应该可以:
library("dplyr")
df <- tbl_df(as.data.frame(cbind(c(rep(1, 4), rep(2, 4)),
c(abs(rnorm(4)), rep(NA, 4)))))
names(df) <- c("group", "var")
df <- df %>%
group_by(group) %>%
mutate(total = sum(var, na.rm = TRUE))
df <- as.data.frame(df)
CheckDay <- function(x) {
if( all( (x[x$group == 2, ])$total == 0) ) {
x$var <- x[x$group == 1, 2]
}
x
}
result <- do(df, CheckDay(.))
print(result)
库(“dplyr”)
df为了扩展Brouwer的答案,以下是我为实现我的目标而实施的措施:
- 如前所述生成
df
- 创建
df.shift
,一份包含组1、1、2的df副本。。。etc——即变量下移一组的df。(df.shift的df.shift
组1中的行也可以是空的。)
- 获取
total=0
的索引,并将值从df复制到这些索引处的df
这一切都可以在base R中完成。它创建一个副本,但比在组上循环要便宜得多,速度也快得多 如果需要的话,我愿意使用base或data.table。我认为我需要在CheckDay中有效地使用df作为全局变量(利用它始终存在于CheckDay的父环境中这一事实)。我看那没必要。非常感谢。但我仍然需要弄清楚如何对其进行泛化,以便对于更大的数据帧,它将从前面的组(而不是示例中指定的组)中获取值。也许我可以在一个因子上分组,并使用因子级别作为代理?你应该能够轻松地循环所有的分组号,将它们存储在一个向量中。无论何时,只要所有组总数0
都抓住组向量中的上一个条目,并相应地设置var
。循环是我希望避免的,因为我有5788个组。但是,一旦我有了零数据的索引(我可以从df$total==0获得),我就可以用df$var的预移位副本中的值来替换这些索引。
Error: Results are not data frames at positions: 1, 2
library("dplyr")
df <- tbl_df(as.data.frame(cbind(c(rep(1, 4), rep(2, 4)),
c(abs(rnorm(4)), rep(NA, 4)))))
names(df) <- c("group", "var")
df <- df %>%
group_by(group) %>%
mutate(total = sum(var, na.rm = TRUE))
df <- as.data.frame(df)
CheckDay <- function(x) {
if( all( (x[x$group == 2, ])$total == 0) ) {
x$var <- x[x$group == 1, 2]
}
x
}
result <- do(df, CheckDay(.))
print(result)