0

我有一个看起来像这样的 CSV 数据..

CUSIP   BuyDate SellDate    BuyAmount   SellAmount  Profit  DaysHolding Over365Days
037833100   12/1/2015   3/1/2017    45  27  -18 456 1
17275R102   1/28/2016   2/21/2017   28  25  -3  390 1
38259P508   10/29/2015  2/18/2017   39  36  -3  478 1
594918104   3/1/2016    3/2/2017    35  40  5   366 1
68389X105   4/14/2016   2/21/2017   47  37  -10 313 0
037833100   12/11/2015  2/19/2017   46  40  -6  436 1
17275R102   1/12/2016   2/24/2017   29  34  5   409 1
38259P508   12/22/2015  2/20/2017   46  39  -7  426 1
594918104   12/19/2015  2/22/2017   26  36  10  431 1
68389X105   2/13/2016   3/2/2017    33  34  1   383 1
037833100   12/9/2015   2/18/2017   32  37  5   437 1
17275R102   2/13/2016   2/27/2017   48  25  -23 380 1
38259P508   11/30/2015  2/23/2017   45  34  -11 451 1
594918104   11/14/2015  2/27/2017   47  28  -19 471 1
68389X105   2/10/2016   2/17/2017   39  38  -1  373 1
037833100   4/7/2016    3/5/2017    44  29  -15 332 0
17275R102   3/3/2016    2/19/2017   26  36  10  353 0
037833100   11/25/2015  2/17/2017   28  40  12  450 1
037833100   1/10/2016   3/6/2017    35  36  1   421 1
037833100   3/4/2016    2/22/2017   45  25  -20 355 0
38259P508   2/10/2016   3/7/2017    42  40  -2  391 1
38259P509   12/5/2015   2/25/2017   31  39  8   448 1
38259P510   4/7/2016    2/27/2017   27  34  7   326 0
38259P511   3/26/2016   2/17/2017   27  39  12  328 0
17275R102   2/11/2016   2/27/2017   29  39  10  382 1
17275R102   11/24/2015  2/18/2017   45  35  -10 452 1
38259P509   3/29/2016   3/7/2017    46  27  -19 343 0
38259P509   4/5/2016    2/23/2017   38  38  0   324 0
17275R102   2/13/2016   2/26/2017   35  31  -4  379 1
594918104   3/10/2016   3/4/2017    29  28  -1  359 0
17275R102   10/30/2015  2/23/2017   40  30  -10 482 1
17275R102   12/15/2015  3/2/2017    25  38  13  443 1
594918104   2/2/2016    2/22/2017   26  32  6   386 1
594918105   3/8/2016    2/20/2017   26  29  3   349 0
594918106   11/21/2015  3/6/2017    44  38  -6  471 1
594918107   3/21/2016   2/20/2017   48  39  -9  336 0
594918108   12/21/2015  3/5/2017    37  28  -9  440 1
594918109   1/16/2016   3/5/2017    35  33  -2  414 1
594918110   2/8/2016    3/2/2017    41  39  -2  388 1

此文件中有数百万行。我想根据 CUSIP 对所有交易进行排序,然后根据利润和 Over365Days 对结果进行小计。这是最终结果应该是什么样子的图像。我只是为效果添加了一些颜色。

在此处输入图像描述

我猜它应该是这样的:

# read csv file
mydata = read.csv("AllTrades.csv")  

# sort by CUSIP, Over365Days
sortdata <- mtcars[order(CUSIP, Over365Days),] 

# aggregate by Profit & 365Days
finalresults <- aggregate(cbind(Profit, Over365Days) ~ CUSIP, data = sortdata, FUN = sum)

我可以在 Excel 中轻松管理小型数据集,但同样需要处理数百万行。有人可以给我一些可以做我描述的示例代码吗?谢谢大家。

4

2 回答 2

2

我必须进行一些清理才能重现您的数据,但这是清理部分之后的结果,我将变量命名为clean_data

> str(clean_data)
'data.frame':   39 obs. of  8 variables:
$ CUSIP      : chr  "037833100" "17275R102" "38259P508" "594918104" ...
$ BuyDate    : chr  "12/1/2015 " "1/28/2016 " "10/29/2015" "3/1/2016  " ...
$ SellDate   : chr  "3/1/2017 " "2/21/2017" "2/18/2017" "3/2/2017 " ...
$ BuyAmount  : num  45 28 39 35 47 46 29 46 26 33 ...
$ SellAmount : num  27 25 36 40 37 40 34 39 36 34 ...
$ Profit     : num  -18 -3 -3 5 -10 -6 5 -7 10 1 ...
$ DaysHolding: num  456 390 478 366 313 436 409 426 431 383 ...
$ Over365Days: num  1 1 1 1 0 1 1 1 1 1 ...

然后我复制了 10 倍的数据集以提供稍大的数据大小,这样输出会更有意义并命名它new_data

new_data <- plyr::ldply(1:10, function(i){
  clean_data
})

由于 Excel 格式与我们在操作和聚合后轻松访问数据的方式不一致,因此我存储结果的方式与您在 excel 中的存储方式略有不同(......相信我......我多年来一直是一名分析师......它需要习惯,但现在我永远不会回到数据透视表......)

因此,这些步骤是针对每个单独的 CUSIP,我们将把数据集“分块”到仅属于该身份集的那些记录中。IE 对于 N 个唯一的 CUSIP id,我们将使用该split 方法创建 N[m,j] 个分片数据子集。我们还将把它包装在一个循环中,这样我们只需应用一次聚合公式,但将应用到每个子集。对于 N 个唯一 CUSIP id 领域中的每个数据帧,我们将返回一个列表,其中包含 1) 原始分块数据 2) 利润 3) 总计

out_split <- lapply(split(new_data, new_data$CUSIP), function(i){
  list(
    data_subset = i, # This is the data unique to the CUSIP id
    profit_calc = sum(i[['Profit']]), # This is the sum of profits
    total = sum(i[['Over365Days']]) # This is the sum of 365 roll
  )
})

现在我们可以通过访问返回的列表中的 CUSIP id 来调用我们的数据并找到我们想要的任何内容。例如:

> out_split$`594918106`
$data_subset
        CUSIP    BuyDate  SellDate BuyAmount SellAmount Profit DaysHolding Over365Days
35  594918106 11/21/2015 3/6/2017         44         38     -6         471           1
74  594918106 11/21/2015 3/6/2017         44         38     -6         471           1
113 594918106 11/21/2015 3/6/2017         44         38     -6         471           1
152 594918106 11/21/2015 3/6/2017         44         38     -6         471           1
191 594918106 11/21/2015 3/6/2017         44         38     -6         471           1
230 594918106 11/21/2015 3/6/2017         44         38     -6         471           1
269 594918106 11/21/2015 3/6/2017         44         38     -6         471           1
308 594918106 11/21/2015 3/6/2017         44         38     -6         471           1
347 594918106 11/21/2015 3/6/2017         44         38     -6         471           1
386 594918106 11/21/2015 3/6/2017         44         38     -6         471           1

$profit_calc
[1] -60

$total
[1] 10

此外,我们可以找到所有计算的总数:(因为总数在每次迭代中存储为第 3 项)

 > sapply(out_split, `[[`, 3)
    037833100 17275R102 38259P508 38259P509 38259P510 38259P511 594918104 594918105 594918106 594918107 594918108 594918109 594918110 68389X105 
           50        80        40        10         0         0        40         0        10         0        10        10        10        20 

如果我们想看到利润:

> sapply(out_split, `[[`, 2)
037833100 17275R102 38259P508 38259P509 38259P510 38259P511 594918104 594918105 594918106 594918107 594918108 594918109 594918110 68389X105 
     -410      -120      -230      -110        70       120        10        30       -60       -90       -90       -20       -20      -100 

编辑

我意识到示例输出是在一个只有一个记录的集合上......所以要展示另一个和另外的如何轻松访问它:

> out_split$`037833100`$data_subset$Profit
 [1] -18  -6   5 -15  12   1 -20 -18  -6   5 -15  12   1 -20 -18  -6   5 -15  12   1 -20 -18  -6   5 -15  12   1 -20 -18  -6   5 -15  12   1 -20 -18  -6   5 -15  12
[41]   1 -20 -18  -6   5 -15  12   1 -20 -18  -6   5 -15  12   1 -20 -18  -6   5 -15  12   1 -20 -18  -6   5 -15  12   1 -20

任何想要复制的人的数据集重建步骤:

clean_data <- stringi::stri_split_lines('
CUSIP   BuyDate SellDate    BuyAmount   SellAmount  Profit  DaysHolding Over365Days
037833100   12/1/2015   3/1/2017    45  27  -18 456 1
17275R102   1/28/2016   2/21/2017   28  25  -3  390 1
38259P508   10/29/2015  2/18/2017   39  36  -3  478 1
594918104   3/1/2016    3/2/2017    35  40  5   366 1
68389X105   4/14/2016   2/21/2017   47  37  -10 313 0
037833100   12/11/2015  2/19/2017   46  40  -6  436 1
17275R102   1/12/2016   2/24/2017   29  34  5   409 1
38259P508   12/22/2015  2/20/2017   46  39  -7  426 1
594918104   12/19/2015  2/22/2017   26  36  10  431 1
68389X105   2/13/2016   3/2/2017    33  34  1   383 1
037833100   12/9/2015   2/18/2017   32  37  5   437 1
17275R102   2/13/2016   2/27/2017   48  25  -23 380 1
38259P508   11/30/2015  2/23/2017   45  34  -11 451 1
594918104   11/14/2015  2/27/2017   47  28  -19 471 1
68389X105   2/10/2016   2/17/2017   39  38  -1  373 1
037833100   4/7/2016    3/5/2017    44  29  -15 332 0
17275R102   3/3/2016    2/19/2017   26  36  10  353 0
037833100   11/25/2015  2/17/2017   28  40  12  450 1
037833100   1/10/2016   3/6/2017    35  36  1   421 1
037833100   3/4/2016    2/22/2017   45  25  -20 355 0
38259P508   2/10/2016   3/7/2017    42  40  -2  391 1
38259P509   12/5/2015   2/25/2017   31  39  8   448 1
38259P510   4/7/2016    2/27/2017   27  34  7   326 0
38259P511   3/26/2016   2/17/2017   27  39  12  328 0
17275R102   2/11/2016   2/27/2017   29  39  10  382 1
17275R102   11/24/2015  2/18/2017   45  35  -10 452 1
38259P509   3/29/2016   3/7/2017    46  27  -19 343 0
38259P509   4/5/2016    2/23/2017   38  38  0   324 0
17275R102   2/13/2016   2/26/2017   35  31  -4  379 1
594918104   3/10/2016   3/4/2017    29  28  -1  359 0
17275R102   10/30/2015  2/23/2017   40  30  -10 482 1
17275R102   12/15/2015  3/2/2017    25  38  13  443 1
594918104   2/2/2016    2/22/2017   26  32  6   386 1
594918105   3/8/2016    2/20/2017   26  29  3   349 0
594918106   11/21/2015  3/6/2017    44  38  -6  471 1
594918107   3/21/2016   2/20/2017   48  39  -9  336 0
594918108   12/21/2015  3/5/2017    37  28  -9  440 1
594918109   1/16/2016   3/5/2017    35  33  -2  414 1
594918110   2/8/2016    3/2/2017    41  39  -2  388 1
', omit_empty = TRUE)[[1]] %>% 
  stringi::stri_split_regex("\\s+", simplify = TRUE) %>% (function(x){
    col_names <- x[1,]
    a_data <- data.frame(x[2:nrow(x),], stringsAsFactors = FALSE)
    colnames(a_data) <- col_names
    as.data.frame(Map(function(i){
      .call_col <- sprintf("as.%s",readr::guess_parser(i))
      do.call(.call_col, list(i))
    }, a_data))
  })
于 2017-03-09T15:24:50.650 回答
1

这个聚合是一个简单的单行dplyr(或data.table) - (你完全不需要对你的数据框进行预排序):

require(dplyr)

summaryresults <- mydata %>%
    group_by(CUSIP) %>%
    summarize(Profit = sum(Profit), Over365Days = sum(Over365Days)) %>%
    ungroup()
    # %>% arrange(CUSIP, Over365Days) # ...if you want the summary result ordered by those vars

dplyr是 的继承者plyr,并且非常易于使用和直观,带有动词,如、mutatesummarizefilter和其他。请参阅介绍或教程:https ://cran.rstudio.com/web/packages/dplyr/vignettes/introduction.htmlselectarrange

于 2017-03-09T15:41:42.810 回答