r - 使用 ifelse 和 group by 改变 data.table 中的列
问题描述
我有一些 dplyr 代码要移至 data.table,这是我刚刚遇到的问题。如果大于或等于,我希望b
存储在列中的从一行到下一行的差异。但是运行此代码后:c
a
3
df = data.frame(a = c(1, 1, 1, 1, 2, 2, 2, 3, 3, 3, 3),
b = c(0, 1, 0, 1, 0, 1, 1, 0, 3, 4, 5))
setDT(df)
df[ , c := ifelse(a >= 3, c(0, diff(b)), b), by = .(a)]
里面的所有元素c
都是0。这是为什么呢?
df
a b c
1: 1 0 0
2: 1 1 0
3: 1 0 0
4: 1 1 0
5: 2 0 0
6: 2 1 0
7: 2 1 0
8: 3 0 0
9: 3 3 0
10: 3 4 0
11: 3 5 0
我认为是等效的 dplyr:
df = data.frame(a = c(1, 1, 1, 1, 2, 2, 2, 3, 3, 3, 3),
b = c(0, 1, 0, 1, 0, 1, 1, 0, 3, 4, 5))
df %>%
group_by(a) %>%
mutate(c = ifelse( a >= 3, c(0, diff(b)), b))
解决方案
从 for 的帮助中ifelse(test, yes, no)
,它应该返回...
与来自 yes 或 no 值的测试和数据值具有相同长度和属性(包括维度和“类”)的向量。答案的模式将被强制从逻辑中获取,以首先容纳取自 yes 的任何值,然后容纳取自 no 的任何值。
然而:
> df %>% group_by(a) %>% do(print(.$a))
[1] 1 1 1 1
[1] 2 2 2
[1] 3 3 3 3
> data.table(df)[, print(a), by=a]
[1] 1
[1] 2
[1] 3
如帮助页面中所述,由于第一个参数的长度为 1,如果您为其他部分传递向量,则仅使用它们的第一个元素:
> ifelse(TRUE, 1:10, eleventy + million)
[1] 1
您可能应该if ... else ...
在使用常量值时使用,例如...
> data.table(df)[, b := if (a >= 3) c(0, diff(b)) else b, by=a]
甚至更好,在这种情况下,您可以分配给一个子集:
> data.table(df)[a >= 3, b := c(0, diff(b)), by=a]
关于为什么a
data.table 习语的长度为 1,请参阅其常见问题解答问题“在每个组内,为什么组变量长度为 1?”
推荐阅读
- r - 用特定字符之间的键分隔(dplyr)(在空格之后和大写字母之前)
- typescript - 从打字稿界面创建形状
- vba - 文本框是对另一个文本框的引用,需要返回第二个文本框中的内容的值
- python - ValueError: `sequences` 在 Keras 中必须是可迭代的
- reactjs - React router V4 - 同一页面上有 2 条差异路由的问题
- ios - 在 Swift 中随时随地计算数据时如何改进 UITableView 的滚动?
- r - 缺失时间序列数据的估算预测几乎是静止的(平线)
- docker - 用 PHP/Laravel 连接 CitusData
- linux - 如何在 Linux 中的列中换行
- python - 什么时候使用 npz 文件而不是 csv 更好?