你的方法是一个不错的开始!
my.DT <- myDT[,.(Type=Type, number_of_offices=nrow(my.DT[my.DT$Type=="office",]), number_of_apartments=nrow(my.DT$Type=="apparment",], by="Property")
括号不匹配,我猜测是复制粘贴时出现了一些错误。这些错误可以通过遵循
如何创建一个完美的可重现示例和使用
reprex
包来有效地避免。你的问题中的代码可能看起来像这样:
library(data.table)
rooms_dt <- fread(text =
"Property Type
1 apartment
1 office
2 office
2 office
3 apartment
3 apartment
3 office
")
rooms_dt[, .(
Type=Type,
number_of_offices=nrow(rooms_dt[rooms_dt$Type=="office",]),
number_of_apartments=nrow(rooms_dt[rooms_dt$Type=="apartment",])
), by="Property"]
由 reprex 包(v0.3.0)于2020-03-12创建
正如您注意到的那样,该方法的问题在于对于每个组(=每个Property
),都会评估用于每个组的 j
表达式,计算出所有公寓/办公室行的数量,而不仅仅是当前 Property
的数量。这可以通过不仅针对正确类型而且还针对正确的属性进行子集划分(在j
中作为特殊变量.BY
可用)来避免。这已经得到了所需的结果:
rooms_dt[, .(
Type=Type,
number_of_offices=nrow(rooms_dt[rooms_dt$Property == .BY & rooms_dt$Type=="office",]),
number_of_apartments=nrow(rooms_dt[rooms_dt$Property == .BY & rooms_dt$Type=="apartment",])
), by="Property"]
然而,这个解决方案可以被简化很多:
首先,data.table
的列可以直接通过它们的名称在[]
中访问:
rooms_dt[, .(
Type=Type,
number_of_offices=nrow(rooms_dt[Property == .BY & Type=="office",]),
number_of_apartments=nrow(rooms_dt[Property == .BY & Type=="apartment",])
), by="Property"]
此外,
data.table
提供了将当前数据表子集化到当前组的
.SD
,从而使其进一步简化。
rooms_dt[, .(
Type=Type,
number_of_offices=nrow(.SD[Type=="office",]),
number_of_apartments=nrow(.SD[Type=="apartment",])
), by="Property"]
由于不仅.SD被子集化,而且所有列都被子集化,因此直接使用它们更加简单:
rooms_dt[, .(
Type = Type,
number_of_offices = sum(Type=="office"),
number_of_apartments = sum(Type=="apartment")
), by="Property"]
data.table
的一个优点是,与大多数 R
相比,它们是可变的。这使得可以直接将新列添加到旧的 data.table
中,而无需创建新的表:
rooms_dt[, number_of_offices := sum(Type=="office"), by="Property"]
rooms_dt[, number_of_apartments := sum(Type=="apartment"), by="Property"]
这也可以写成:
rooms_dt[, c("number_of_offices", "number_of_apartments") := list(sum(Type=="office"), sum(Type=="apartment")), by="Property"]
或者作为:
rooms_dt[, `:=`(number_of_offices = sum(Type=="office"), number_of_apartments = sum(Type=="apartment")), by="Property"]
这并不像可能的那样容易,可能是因为它很少需要,通常更希望有其中之一:
rooms_dt[, count_in_property := .N, by=.(Property, Type)]
rooms_dt
或者
dcast(rooms_dt[, .(number_of = .N), by=.(Property, Type)], Property ~ Type, fill = 0)