我在下面有一个数据框(df),我想使用dplyr添加一个额外的列result
,如果z == "gone"
和x
是y
,它将取值1组 y x z
1 a 3 gone
2 a 5 gone
3 a 8 gone
4 a 9 gone
5 a 10 gone
6 b 1
7 b 2
8 b 4
9 b 6
10 b 7
的最大值。
df %>%
group_by(y) %>%
slice(which.max(x))
如果我只是为每个组选择最大值,那就是:
y x z
1 a 10 gone
2 b 7
将返回:
x
这不是我想要的。我需要利用y
中每个组的z == "gone"
的最大值,同时检查是否TRUE
,如果 y x z result
1 a 3 gone 0
2 a 5 gone 0
3 a 8 gone 0
4 a 9 gone 0
5 a 10 gone 1
6 b 1 0
7 b 2 0
8 b 4 0
9 b 6 0
10 b 7 0
则为1,否则为0.这看起来像:
mutate()
我假设我会在 db.books.find({}, function(err, books) {
for (var i = 0; i < books.length; i++) {
var book = books[i];
user.cart.forEach(function(item) {
console.log(book._id == item.id)
if (item.id == book._id) {
var _item = book;
_item.qty = item.qty;
cart.push(_item);
return false;
}
})
};
// res, status, data, message, err
respHandler(res, 200, cart, 'Success', null);
});
中使用条件语句,但我似乎无法找到一个例子。请指教。
答案 0 :(得分:6)
我们可以使用data.table
执行此操作。我们将'data.frame'转换为'data.table'(setDT(df)
),按'y'分组,我们创建'x'的最大值的逻辑条件和'z'中的'gone'元素,将其强制转换为“整数”(as.integer
)并将输出分配(:=
)到新列(“结果”)。
library(data.table)
setDT(df)[, result := as.integer(x==max(x) & z=='gone') , by = y]
df
# y x z result
# 1: a 3 gone 0
# 2: a 5 gone 0
# 3: a 8 gone 0
# 4: a 9 gone 0
# 5: a 10 gone 1
# 6: b 1 0
# 7: b 2 0
# 8: b 4 0
# 9: b 6 0
#10: b 7 0
或者我们可以使用ave
base R
df$result <- with(df, +(ave(x, y, FUN=max)==x & z=='gone' ))
答案 1 :(得分:5)
使用dplyr
,您可以使用:
df %>% group_by(y) %>% mutate(result = +(x == max(x) & z == 'gone'))
+(..)
表示法是as.integer
强制将逻辑输出强制转换为1&0和0的简写。有些人不喜欢它,所以它的代码与可读性相比更短。效率提升可以在这种情况下进行辩论。
同样要了解data.table
和dplyr
使用R进行数据操作所做的事情,让我们在老式的&#34; split-apply-combine&#中做同样的事情34;方式:
#split data.frame by group
split.df <- split(df, df$y)
#apply required function to each group
lst <- lapply(split.df, function(dfx) {
dfx$result <- +(dfx$x == max(dfx$x) & dfx$z == "gone")
dfx})
#combine result in new data.frame
newdf <- do.call(rbind, lst)