我的数据集的简化版本如下:
depth value
1 a
1 b
2 a
2 b
2 b
3 c
我想创建一个新的数据集,对于每个“深度”值,我将从顶部开始具有唯一值的累积数量。 e.g。
depth cumsum
1 2
2 2
3 3
关于如何做到这一点的任何想法?我对R来说比较新。
答案 0 :(得分:13)
我发现这是使用factor
并仔细设置levels
的完美案例。我会在这里使用data.table
这个想法。确保您的value
列为character
(非绝对要求)。
第1步:只需data.frame
行即可将data.table
转换为unique
。
require(data.table)
dt <- as.data.table(unique(df))
setkey(dt, "depth") # just to be sure before factoring "value"
第2步:将value
转换为factor
并强制转换为numeric
。确保自己设置级别(这很重要)。
dt[, id := as.numeric(factor(value, levels = unique(value)))]
第3步:将关键列设置为depth
进行子集化,选择最后一个值
setkey(dt, "depth", "id")
dt.out <- dt[J(unique(depth)), mult="last"][, value := NULL]
# depth id
# 1: 1 2
# 2: 2 2
# 3: 3 3
第4步:由于深度增加的行中的所有值都应至少前一行的值,因此应使用cummax
来获取最终输出。
dt.out[, id := cummax(id)]
修改:上述代码仅供参考。实际上,您根本不需要第3列。这就是我写最终代码的方式。
require(data.table)
dt <- as.data.table(unique(df))
setkey(dt, "depth")
dt[, value := as.numeric(factor(value, levels = unique(value)))]
setkey(dt, "depth", "value")
dt.out <- dt[J(unique(depth)), mult="last"]
dt.out[, value := cummax(value)]
这是一个更棘手的例子和代码的输出:
df <- structure(list(depth = c(1, 1, 2, 2, 3, 3, 3, 4, 5, 5, 6),
value = structure(c(1L, 2L, 3L, 4L, 1L, 3L, 4L, 5L, 6L, 1L, 1L),
.Label = c("a", "b", "c", "d", "f", "g"), class = "factor")),
.Names = c("depth", "value"), row.names = c(NA, -11L),
class = "data.frame")
# depth value
# 1: 1 2
# 2: 2 4
# 3: 3 4
# 4: 4 5
# 5: 5 6
# 6: 6 6
答案 1 :(得分:6)
这是另一次尝试:
numvals <- cummax(as.numeric(factor(mydf$value)))
aggregate(numvals, list(depth=mydf$depth), max)
给出了:
depth x
1 1 2
2 2 2
3 3 3
它似乎也适用于@ Arun的例子:
depth x
1 1 2
2 2 4
3 3 4
4 4 5
5 5 6
6 6 6
答案 2 :(得分:4)
一个好的第一步是创建一个TRUE
或FALSE
列,其中每个值的第一个为TRUE
,以后FALSE
为duplicated
那个价值。这可以使用mydata$first.appearance = !duplicated(mydata$value)
:
aggregate
最好使用first.appearance
重塑数据。在这种情况下,它表示要对depth
的每个子集中的newdata = aggregate(first.appearance ~ depth, data=mydata, FUN=sum)
列求和:
depth first.appearance
1 1 2
2 2 0
3 3 1
结果如下:
cumsum
但这仍然不是累积金额。为此,您可以使用newdata$cumsum = cumsum(newdata$first.appearance)
newdata$first.appearance = NULL
函数(然后删除旧列):
mydata$first.appearance = !duplicated(mydata$value)
newdata = aggregate(first.appearance ~ depth, data=mydata, FUN=sum)
newdata$cumsum = cumsum(newdata$first.appearance)
newdata$first.appearance = NULL
所以回顾一下:
depth cumsum
1 1 2
2 2 2
3 3 3
输出:
{{1}}
答案 3 :(得分:4)
使用sqldf包可以使用单个SQL语句以相对干净的方式编写。假设DF
是原始数据框:
library(sqldf)
sqldf("select b.depth, count(distinct a.value) as cumsum
from DF a join DF b
on a.depth <= b.depth
group by b.depth"
)
答案 4 :(得分:1)
以下是使用lapply()
的另一种解决方案。使用unique(df$depth)
制作唯一depth
值的向量,然后对于每个此类值子集,只有value
值等于或小于特定depth
值的depth
值。然后计算唯一value
值的长度。此长度值存储在cumsum
中,然后depth=x
将提供特定深度级别的值。使用do.call(rbind,...)
将其设为一个数据框。
do.call(rbind,lapply(unique(df$depth),
function(x)
data.frame(depth=x,cumsum=length(unique(df$value[df$depth<=x])))))
depth cumsum
1 1 2
2 2 2
3 3 3
答案 5 :(得分:0)
dplyr的尝试。
MessageHandler