混合数据帧的总和取决于 R 中的多个条件
Posted
技术标签:
【中文标题】混合数据帧的总和取决于 R 中的多个条件【英文标题】:Sum of hybrid data frames depending on multiple conditions in R 【发布时间】:2013-02-09 06:15:52 【问题描述】:这是对我之前的question 的更复杂的后续。答案是使用矩阵,但这不适用于具有不同模式值的数据帧。
我想将不同大小的数据框与字符列和整数列组合起来,并根据多个条件计算它们的总和。
条件
-
只为那些具有匹配“名称”值的行计算总和
仅针对匹配的列名计算总和
如果
df4
中的单元格不为0且不为NA,则总和应为df3 + df4
否则总和应该是df1 + df2 + df3
示例
> df1 <- data.frame(Name=c("Joe","Ann","Lee","Dan"), "1"=c(0,1,5,2), "2"=c(3,1,0,0), "3"=c(2,0,2,2), "4"=c(2,1,3,4))
> df1
Name X1 X2 X3 X4
1 Joe 0 3 2 2
2 Ann 1 1 0 1
3 Lee 5 0 2 3
4 Dan 2 0 2 4
> df2 <- data.frame(Name=c("Joe","Ann","Ken"), "1"=c(3,4,1), "2"=c(2,3,0), "3"=c(2,4,3))
> df2
Name X1 X2 X3
1 Joe 3 2 2
2 Ann 4 3 4
3 Ken 1 0 3
> df3 <- data.frame(Name=c("Lee","Ben"), "1"=c(1,3), "2"=c(3,4), "3"=c(4,3))
> df3
Name X1 X2 X3
1 Lee 1 3 4
2 Ben 3 4 3
条件取决于这个框架:
> df4 <- data.frame(Name=c("Lee","Ann","Dan"), "1"=c(6,0,NA), "2"=c(0,0,4), "3"=c(0,NA,0))
> df4
Name X1 X2 X3
1 Lee 6 0 0
2 Ann 0 0 NA
3 Dan NA 4 0
对于上述示例,这是预期的结果(* 值取决于 df4):
> dfsum
Name X1 X2 X3 X4
1 Joe 3 5 4 2
2 Ann 5 4 4 1
3 Lee 7* 3 6 3
4 Dan 2 4* 2 4
5 Ken 1 0 3 NA
6 Ben 3 4 3 NA
可能的步骤?
先将df1、df2、df3、df4扩展为5列6行,用NA填充缺失数据。
那么对于每个数据框:
-
按“名称”对行进行排序
将“名称”列与“X1”...“X4”分开
将“X1”...“X4”列转换为矩阵
计算矩阵的总和,就像我的另一个问题的答案一样但有附加条件 1
将结果矩阵转换为数据框
将“名称”列与结果数据框绑定
如何在 R 中做到这一点?
解决方案
@Ricardo Saporta 的解决方案只需稍加改动即可工作:
在四个 addCols() 中添加, padValue=NA)
。
如回答here,将 sumD3D4 和 dtsum 的定义替换为:
plus <- function(x)
if(all(is.na(x)))
c(x[0],NA) else
sum(x,na.rm = TRUE)
sumD3D4 <- setkey(rbind(dt3, dt4)[,lapply(.SD, plus), by = Name], "Name")
dtsum <- setkey(rbind(dt1, dt2, dt3)[, lapply(.SD, plus), by=Name], "Name")
【问题讨论】:
看来character
s 的唯一作用是名称。那是对的吗 ?如果是这样,您仍然可以使用推荐的矩阵方法并将字符串应用于rownames(mtrx)
另外,关于不同的列数,是否可以添加虚拟列以填充 0 以使所有 df 的宽度相同?
它们应该是NA,但是在计算两个矩阵之和时是否可以将NA视为0?
【参考方案1】:
如果您使用 data.table 而不是 data.frame,您可以使用其by=xxxx
功能,按名称添加。
下面的代码应该会给你预期的结果。
请注意,我正在使用额外的空列填充 data.tables。但是,我们在此之前计算 condTrue
。
library(data.table)
dt1 <- data.table(df1)
dt2 <- data.table(df2)
dt3 <- data.table(df3)
dt4 <- data.table(df4)
# make sure all dt's have the same columns
#-----------------------------------------#
# identify which dt4 satisfy the condition
condTrue <- as.data.table(which(!(is.na(dt4) | dt4==0), arr.ind=TRUE))
# ignore column "Name" from dt4
condTrue <- condTrue[col>1]
# convert from (row, col) index to ("Name", columnName)
condTrue <- data.table(Name=dt4[condTrue$row, Name], colm=names(dt4)[condTrue$col], key="Name")
# First make a list of all the unique column names
allColumnNames <- unique(c(names(dt1), names(dt2), names(dt3), names(dt4)))
# add columns as necessary, using addCols (definted below)
addCols(dt1, allColumnNames)
addCols(dt2, allColumnNames)
addCols(dt3, allColumnNames)
addCols(dt4, allColumnNames)
sumD3D4 <- setkey(rbind(dt3, dt4)[, lapply(.SD, sum), by=Name], "Name")
dtsum <- setkey(rbind(dt1, dt2, dt3)[, lapply(.SD, sum), by=Name], "Name")
for (Nam in condTrue$Name)
colsRepl <- condTrue[.(Nam)]$colm
valsRepl <- unlist(sumD3D4[.(Nam), c(colsRepl), with=FALSE])
dtsum[.(Nam), c(colsRepl) := as.list(valsRepl)]
dtsum
# Name 1 2 3 4
# 1: Ann 5 4 4 1
# 2: Ben 3 4 3 0
# 3: Dan 2 4 2 4
# 4: Joe 3 5 4 2
# 5: Ken 1 0 3 0
# 6: Lee 7 3 6 3
addCols <- function(x, cols, padValue=0)
# adds to x any columns that are in cols but not in x
# Returns TRUE if columns were added
# FALSE if no columns added
colsMissing <- setdiff(cols, names(x))
# grab the actual DT name that was passed to function
dtName <- as.character(match.call()[2])
if (length(colsMissing))
get(dtName, envir=parent.frame(1))[, c(colsMissing) := padValue]
return(TRUE)
return(FALSE)
【讨论】:
不错。有时我想知道人们是如何陷入这些困境的。但是解决它们会带来一些有趣的难题。 非常好。但是如何在 X4 列中保留 Ken 和 Ben 的 NA? @R-obert,您上面的评论说您想将 NA 视为 0。请注意,您要查找的 NA 在第 4 列中显示为 0。如果您想改用 NA,只需在四个addCols()
语句中添加 , padValue=NA)
。但是请注意,它会将所有 NA cols 变成结果中的 NA。如果您希望仅选择性地传递 NA,则需要在上面添加更多条件语句。
我上面的评论不清楚。我想使用 NA,但它仍然不起作用。添加, padValue=NA)
会导致:Error in [.data.table'(dtsum, .(Nam), ':='(c(colsRepl), as.list(valsRepl))): Type of RHS ('double') must match LHS ('integer'). To check and coerce would impact performance too much for the fastest cases. Either change the type of the target column, or coerce the RHS of := yourself (e.g. by using 1L instead of 1)
我很抱歉@R-obert,但仍然不太清楚 "to use NA's" 的具体含义。你不想在哪里使用它们,你想如何使用它们?以上是关于混合数据帧的总和取决于 R 中的多个条件的主要内容,如果未能解决你的问题,请参考以下文章