【问题标题】:how to use apply family instead of nested for loop for my problem如何为我的问题使用应用系列而不是嵌套的 for 循环
【发布时间】:2020-05-17 19:10:46
【问题描述】:

我想根据名为 dfnew1 的旧数据框的条件填充一个名为 hd5 的新数据框。

我可以不使用嵌套的for 循环吗?

   for(  j in 2 : length(hd6)  )
   {
     for( i in 1: length(hd5$DATE) )
    {
     abcd= dfnew1 %>%  
     filter( (Date == hd5$DATE[i]) , (StrikePrice== hd6[j]) , (OptionType== "CE"))  %>%
     arrange( dte  )          
     hd5[i,j]= abcd[1,9]
     }
   }

hd6= [13900,14000,14100,14200]

dfnew1 看起来像这样

Date     expiry     optiontype strikeprice closeprice  dte
1/1/2019  31/1/2019  ce          13900      700        30
1/1/2019  31/1/2019  ce          14000      650        30
1/1/2019  31/1/2019  ce          14100      600        30
1/1/2019  31/2/2019  ce          14100      900        58
1/2/2019  31/1/2019  ce          13900      800        29
1/2/2019  31/1/2019  ce          14000      750        29
1/2/2019  31/1/2019  ce          14100      700        29

我想通过处理日期和 strtkeprice 和 optiontype 从这个 dfnew1 数据帧填充我的新数据帧 hd5

我要填充的hd5应该是这样的

Date         13900  14000 14100 14200
1/1/2019     700     650   600   550
1/2/2019     800     750   700   650

【问题讨论】:

  • 能否请您添加 (a) 来自 hd5 的一些代表性数据 - 比如 5 - 10 行,以及 (b) 您希望 hd6 看起来像什么?
  • 是的,但我要求您编辑您的帖子,以便我们可以看到 hd5 的样子,以及您想要 hd6 的样子。
  • 你有 3 个数据集,即 hd6、hd5 和 dfnew1
  • 是的。我有 3 个数据集。
  • @r2evans 现在正确吗??

标签: r for-loop apply


【解决方案1】:

这是一个 tidyverse 选项:

library(dplyr)
# library(tidyr)
dat %>%
  group_by(Date, strikeprice) %>%
  summarize(closeprice = min(closeprice)) %>%
  ungroup() %>%
  tidyr::pivot_wider(names_from = "strikeprice", values_from = "closeprice")
# # A tibble: 2 x 4
#   Date     `13900` `14000` `14100`
#   <chr>      <int>   <int>   <int>
# 1 1/1/2019     700     650     600
# 2 1/2/2019     800     750     700

(您可能会看到引用tidyr::spread 的在线教程。它在此处有效地执行相同的操作,但一直是retired(来源:https://tidyr.tidyverse.org/reference/spread.html,以及tidyr::gather),因此通常建议使用新代码应该使用pivot_* 函数。)

注意:根据您的预期输出,看起来您为

1/1/2019  31/1/2019  ce          14100      600        30
1/1/2019  31/2/2019  ce          14100      900        58

我可能更倾向于(当涉及“价格”时)改用sum,但这在很大程度上取决于您的实际意图和使用情况。将 min 替换为您选择的聚合,无论是 maxsum 还是其他。

我会注意到,使用数字列名称有点不标准,并且可能会导致混淆(dat[,14100] 将失败,dat[,\14100`]ordat[,"14100"]` 通常应该可以工作)。

您可能会发现使用数字列标题对于某些比较和描述 表格 是有意义的,但如果您计划绘制事物(例如,使用 ggplot2),通常是更长的版本(您的原始布局,尽管总结)可能是首选。


数据:

dat <- read.table(header = TRUE, stringsAsFactors = FALSE, text = "
Date     expiry     optiontype strikeprice closeprice  dte
1/1/2019  31/1/2019  ce          13900      700        30
1/1/2019  31/1/2019  ce          14000      650        30
1/1/2019  31/1/2019  ce          14100      600        30
1/1/2019  31/2/2019  ce          14100      900        58
1/2/2019  31/1/2019  ce          13900      800        29
1/2/2019  31/1/2019  ce          14000      750        29
1/2/2019  31/1/2019  ce          14100      700        29")

【讨论】:

    【解决方案2】:

    我们也可以用spread汇总后得到'closeprice'按'Date'、'strikeprice'分组后的min

    library(dplyr)
    library(tidyr)
    dat %>%
      group_by(Date, strikeprice) %>%
      slice(which.min(dte)) %>%
      ungroup() %>%
      spread(strikeprice, closeprice)
    # A tibble: 2 x 4
    #  Date     `13900` `14000` `14100`
    #  <chr>      <int>   <int>   <int>
    #1 1/1/2019     700     650     600
    #2 1/2/2019     800     750     700
    

    或者通过使用values_fn 来传递函数来使用pivot_wider。在这里,我们select只关注感兴趣的栏目

    dat %>%
      select(Date, strikeprice, closeprice) %>%     
      pivot_wider(names_from = strikeprice, values_from = closeprice,
           values_fn = list(closeprice = min))
    # A tibble: 2 x 4   
    #  Date     `13900` `14000` `14100`
    #  <chr>      <int>   <int>   <int>
    #1 1/1/2019     700     650     600
    #2 1/2/2019     800     750     700
    

    或者另一个选项是dcast

    library(data.table)
    dcast(setDT(dat), Date  ~ strikeprice, min, value.var = 'closeprice')
    #       Date 13900 14000 14100
    #1: 1/1/2019   700   650   600
    #2: 1/2/2019   800   750   700
    

    数据

    dat <- structure(list(Date = c("1/1/2019", "1/1/2019", "1/1/2019", "1/1/2019", 
    "1/2/2019", "1/2/2019", "1/2/2019"), expiry = c("31/1/2019", 
    "31/1/2019", "31/1/2019", "31/2/2019", "31/1/2019", "31/1/2019", 
    "31/1/2019"), optiontype = c("ce", "ce", "ce", "ce", "ce", "ce", 
    "ce"), strikeprice = c(13900L, 14000L, 14100L, 14100L, 13900L, 
    14000L, 14100L), closeprice = c(700L, 650L, 600L, 900L, 800L, 
    750L, 700L), dte = c(30L, 30L, 30L, 58L, 29L, 29L, 29L)),
    class = "data.frame", row.names = c(NA, 
    -7L))
    

    【讨论】:

    • 我不想要分钟(关闭)。我想要与 min(dte) 对应的收盘价。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-11-12
    • 1970-01-01
    • 1970-01-01
    • 2021-10-08
    • 2012-01-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多