在数据框的每一行中应用条件函数

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在数据框的每一行中应用条件函数相关的知识,希望对你有一定的参考价值。

我是R的新手,我正在努力使用这个看起来像这样的df:

Date      Group       Factor 1 Factor 2 Spread
2019-04-01  a   1.01    1.011   0.01
2019-04-02  a   1.02    1.012   0.02
2019-04-03  a   1.03    1.013   0.03
2019-04-01  b   1.005   1.004   0.01
2019-04-02  b   1.0051  1.0041  0.02
2019-04-03  b   1.0052  1.0042  0.03

我想验证每一行中的每个组,如果结果是组“a”,请执行因子1​​ /因子1(1天滞后)*因子2 +扩散,如果组不是“a”,则不添加扩散。

答案

由于你正在调整这个群体,这是by(基地R),dplyr::group_bydata.tablex[,,by=]的一个很好的例子。

这三个方程实际上是相同的,利用(Group[1] == "a")在被数字乘以时从logical强制到numeric的事实;因为FALSE转换为0,然后有效禁用添加Spread

Base

我在这里使用within来使内部构件更具可读性,但这不是必需的(在这种情况下,您需要在所有变量名称前面添加x$)。

滞后可以使用dplyr::lag(即使你不使用其余的包装)或许多其他技术。我没有发现stats::lag在这样的应用程序中是最直观的,但我相信有人会建议一种方法将它合并到一个答案中。 c(NA, ...)的使用确保我们不会引入不同组的数据或我们没有的数据,因为我们没有任何价值可以引入组的第一行。最后,head(..., n = 1)返回向量/列表的第一个元素,而head(..., n = -1)(负数)返回除最后一个之外的所有元素。

newx <- by(x, x$Group, function(y) {
  within(y, {
    NewVal = Factor2 * Factor1 / c(NA, head(Factor1, n=-1)) + (Group[1] == "a") * Spread
  })
})
newx
# x$Group: a
#         Date Group Factor1 Factor2 Spread   NewVal
# 1 2019-04-01     a    1.01   1.011   0.01       NA
# 2 2019-04-02     a    1.02   1.012   0.02 1.042020
# 3 2019-04-03     a    1.03   1.013   0.03 1.052931
# -------------------------------------------------------
# x$Group: b
#         Date Group Factor1 Factor2 Spread NewVal
# 4 2019-04-01     b  1.0050  1.0040   0.01     NA
# 5 2019-04-02     b  1.0051  1.0041   0.02 1.0042
# 6 2019-04-03     b  1.0052  1.0042   0.03 1.0043

这实际上只是一个list,有一些奇特的by特定的格式,所以你可以把它当作有效的基础-R方式组合它们:

do.call("rbind.data.frame", c(newx, stringsAsFactors = FALSE))
#           Date Group Factor1 Factor2 Spread   NewVal
# a.1 2019-04-01     a  1.0100  1.0110   0.01       NA
# a.2 2019-04-02     a  1.0200  1.0120   0.02 1.042020
# a.3 2019-04-03     a  1.0300  1.0130   0.03 1.052931
# b.4 2019-04-01     b  1.0050  1.0040   0.01       NA
# b.5 2019-04-02     b  1.0051  1.0041   0.02 1.004200
# b.6 2019-04-03     b  1.0052  1.0042   0.03 1.004300

dplyr

许多人发现tidyverse系列包直观地阅读。

library(dplyr)
x %>%
  group_by(Group) %>%
  mutate(NewVal = Factor2 * Factor1 / lag(Factor1) + (Group[1] == "a") * Spread) %>%
  ungroup()
# # A tibble: 6 x 6
#   Date       Group Factor1 Factor2 Spread NewVal
#   <chr>      <chr>   <dbl>   <dbl>  <dbl>  <dbl>
# 1 2019-04-01 a        1.01    1.01   0.01  NA   
# 2 2019-04-02 a        1.02    1.01   0.02   1.04
# 3 2019-04-03 a        1.03    1.01   0.03   1.05
# 4 2019-04-01 b        1.00    1.00   0.01  NA   
# 5 2019-04-02 b        1.01    1.00   0.02   1.00
# 6 2019-04-03 b        1.01    1.00   0.03   1.00

data.table

另一方面,许多人发现data.table更好,因为从就地修改中获得了效率(大多数R的操作都是写时复制,这意味着某些操作会在每次更改时重新复制对象或其中的一部分)。

library(data.table)
X <- as.data.table(x)
X[, NewVal := Factor2 * Factor1 / shift(Factor1) + (Group[1] == "a") * Spread, by = "Group"]
X
#          Date Group Factor1 Factor2 Spread   NewVal
# 1: 2019-04-01     a  1.0100  1.0110   0.01       NA
# 2: 2019-04-02     a  1.0200  1.0120   0.02 1.042020
# 3: 2019-04-03     a  1.0300  1.0130   0.03 1.052931
# 4: 2019-04-01     b  1.0050  1.0040   0.01       NA
# 5: 2019-04-02     b  1.0051  1.0041   0.02 1.004200
# 6: 2019-04-03     b  1.0052  1.0042   0.03 1.004300

“就地”部分在这里的第二行显而易见,似乎[操作应该只返回一个子集或某些数据...但在这种情况下使用:=导致列被创建(或改变了就地。

以上是关于在数据框的每一行中应用条件函数的主要内容,如果未能解决你的问题,请参考以下文章

如何在数据框的每一行上应用函数?

在Pandas中,我如何将一个函数应用到数据框的某一行,其中行中的每一项都应该作为参数传递给函数?

将函数应用于熊猫中数据框的每一列

如何将整个列表分配给熊猫数据框的每一行

map_dfc用于带输入的每一行数据帧

如何在熊猫数据框的每一行中找到选定列中的两个最低值?