检查R中连续几年的捐赠情况

时间:2015-01-05 19:51:08

标签: r csv subset

我在一家非盈利组织工作,有人想要一份在5年内给出100美元或以上的人的名单。跨度可以在任何地方,只要它们连续5年给出。我在计算机上同时拥有Python和R. R似乎对此更好,但我对它不是很熟悉。

我已将每件礼物的csv​​文件导入组织并提供给他们。

以下是csv文件中的示例行。

  • Gf_Gift_ID:1620192
  • Gf_Date:1/31/2005
  • Gf_Amount:25.00
  • Gf_CnBio_ID:512994

我无法在此处正确格式化。第一部分是标题。

我需要能够看到用户512994是否已提供100或更多,例如,2014年,2013年,2012年,2011年和2010年(连续五年)。

到目前为止,我在R脚本中有这个:

gifts <- read.csv("---------")
donors <- gifts["Gf_CnBio_ID"]
donors <- unique(donors)

我一直试图弄清楚如何制作一个较小的数据框,这是一个礼物的子集,通过捐赠者一次一个地分配礼物,然后我检查一下连续多少年那个人给了。我一直在尝试不同的方式来解决错误。

提前致谢。我的大部分背景都是用Java编写的,所以这种语言不是我以前的语言。

此外:

> library(dplyr)
> library(lubridate)
> 
> set.seed(999)
> 
> gifts <- read.csv("---.CSV", header = TRUE, sep = ",", )
> donors <- gifts["Donor_ID"]
> donors <- unique(donors)
> 
> gifts %>%
+   mutate(gift_year = year(gifts["Gift_Date"])) %>% # extract year
+   group_by(gifts["Donor_ID"], gift_year) %>% 
+   summarise(year_gift = sum(gifts["Gift_Amount"])) %>% # total gift per donor/year
+   filter(year_gift >= 100) %>% 
+   group_by(bio_id) %>% 
+   mutate(diff = gift_year - lag(gift_year), rle = rep( rle(diff)$lengths, rle(diff)$lengths)) %>% 
+   filter(rle >= 5) %>% 
+   distinct(bio_id)
Error in as.POSIXlt.default(x, tz = tz(x)) : 
  do not know how to convert 'x' to class “POSIXlt”

尝试运行提供的解决方案时,我一直收到错误输出。我做了一个Python程序,将日期重新格式化为yyyy-mm-dd 00:00:00格式,我仍然得到错误,所以它不是来自日期格式。我不知道造成它的原因。这是前50行。

> dput(shortExport)
structure(list(Gift_ID = c(NA, NA, NA, NA, NA, NA, NA, NA, NA, 
NA, NA, NA, NA, 1620192L, 1630540L, 1661287L, 1670815L, 1702338L, 
1710859L, 1747572L, 1781100L, 1811188L, 1829753L, 1854499L, 1860830L, 
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 
NA, NA, 1361280L, 1246941L, 1355077L, 1243748L, 1243748L, 1518414L
), Gift_Date = structure(c(2L, 23L, 32L, 10L, 17L, 19L, 33L, 
44L, 45L, 11L, 27L, 30L, 47L, 3L, 26L, 9L, 18L, 31L, 37L, 22L, 
28L, 16L, 25L, 34L, 39L, 21L, 42L, 1L, 29L, 35L, 43L, 6L, 13L, 
4L, 5L, 38L, 41L, 46L, 15L, 24L, 40L, 2L, 12L, 20L, 14L, 7L, 
8L, 8L, 36L), .Label = c("1/29/2010 0:00", "1/30/2014 0:00", 
"1/31/2005 0:00", "1/31/2012 0:00", "1/31/2013 0:00", "10/11/2011 0:00", 
"10/18/2000 0:00", "10/27/1998 0:00", "10/31/2005 0:00", "10/31/2011 0:00", 
"10/31/2012 0:00", "11/1/2011 0:00", "11/11/2011 0:00", "11/18/1998 0:00", 
"11/27/2013 0:00", "11/30/2007 0:00", "11/30/2011 0:00", "12/30/2005 0:00", 
"12/30/2011 0:00", "12/6/2000 0:00", "2/27/2009 0:00", "2/28/2007 0:00", 
"2/28/2011 0:00", "2/28/2014 0:00", "2/29/2008 0:00", "3/31/2005 0:00", 
"3/31/2013 0:00", "4/30/2007 0:00", "4/30/2010 0:00", "4/30/2013 0:00", 
"5/31/2006 0:00", "5/31/2011 0:00", "6/29/2012 0:00", "6/30/2008 0:00", 
"6/30/2011 0:00", "7/18/2003 0:00", "7/31/2006 0:00", "7/31/2013 0:00", 
"8/29/2008 0:00", "8/29/2014 0:00", "8/30/2013 0:00", "8/31/2009 0:00", 
"8/31/2011 0:00", "8/31/2012 0:00", "9/28/2012 0:00", "9/30/2013 0:00", 
"9/30/2014 0:00"), class = "factor"), Gift_Amount = c(25L, 25L, 
25L, 25L, 25L, 25L, 25L, 25L, 25L, 25L, 25L, 25L, 25L, 25L, 25L, 
25L, 25L, 25L, 25L, 25L, 25L, 25L, 50L, 50L, 50L, 50L, 50L, 50L, 
50L, 10L, 10L, 100L, 100L, 10L, 10L, 10L, 10L, 10L, 10L, 10L, 
10L, 100L, 250L, 50L, 30L, 25L, 50L, 50L, 50L), Donor_ID = c(677556L, 
521512L, 521512L, 521512L, 521512L, 521512L, 521512L, 521512L, 
521512L, 521512L, 521512L, 521512L, 521512L, 512994L, 512994L, 
512994L, 512994L, 512994L, 512994L, 512994L, 512994L, 512994L, 
512994L, 512994L, 512994L, 512994L, 512994L, 512994L, 512994L, 
512994L, 512994L, 512994L, 512994L, 512994L, 512994L, 512994L, 
512994L, 512994L, 512994L, 512994L, 512994L, 679277L, 406147L, 
331525L, 332110L, 332110L, 263700L, 263701L, 100196L)), .Names = c("Gift_ID", 
"Gift_Date", "Gift_Amount", "Donor_ID"), class = "data.frame", row.names = c(NA, 
-49L))

2 个答案:

答案 0 :(得分:3)

实现您的目标涉及链接许多操作(例如按捐赠者/年汇总,按礼物过滤&gt; $ 100等)。 dplyr包具有很好的设施:

library(dplyr)
library(lubridate)
library(tidyr)

# gifts defined in question

gifts %>%
  mutate(
    gift_date = as.Date(str_sub(Gift_Date, end = -6), format = "%m/%d/%Y"),
    gift_year = year(gift_date) 
  ) %>%   
  group_by(Donor_ID, gift_year) %>% 
  summarise(year_total = sum(Gift_Amount)) %>%
  filter(year_total >= 100) %>% 
  group_by(Donor_ID) %>% 
  mutate(
    jump = !(gift_year == lag(gift_year) + 1 | row_number() == 1),
    donor_seq = cumsum(jump) + 1,
    rle = rep(rle(donor_seq)$lengths, rle(donor_seq)$lengths)
  ) %>%
  filter(rle >= 5) %>% 
  distinct(Donor_ID)

答案 1 :(得分:1)

如果没有实际的样本数据集,我无法告诉您如何提取日期,但我们假设您有一个包含donorID的列,另一个包含礼品日期。然后,循环使用donorID值(或使用一个工具或另一个工具拆分数据集)并使用我自己的一个小函数seqle,可以在github.com/cellocgw github.com/的cgwtools包中找到cellocgw。假设您确定捐赠者在同一年内从未给过两次,那么您所要做的就是找到一个长度超过4的序列。

示例如下。为简单起见,我使用了1到14年左右的时间以及3个捐赠者。

 donmat
      donor   donyear
 [1,] "bob"   "1"    
 [2,] "carol" "1"    
 [3,] "alice" "1"    
 [4,] "bob"   "2"    
 [5,] "carol" "2"    
 [6,] "alice" "3"    
 [7,] "bob"   "3"    
 [8,] "carol" "3"    
 [9,] "alice" "4"    
[10,] "bob"   "5"    
[11,] "carol" "4"    
[12,] "alice" "5"    
[13,] "bob"   "6"    
[14,] "carol" "5"    
[15,] "alice" "7"    
[16,] "bob"   "8"    
[17,] "carol" "7"    
[18,] "alice" "8"    
[19,] "bob"   "9"    
[20,] "carol" "8"    
[21,] "alice" "9"    
[22,] "bob"   "12"   
[23,] "carol" "9"    
[24,] "alice" "11"   
[25,] "bob"   "13"   
[26,] "carol" "9"    
[27,] "alice" "12"   
[28,] "bob"   "14"   
[29,] "carol" "10"   
[30,] "alice" "13"   
Rgames> donlen <- list()
Rgames> for(j in unique(donmat[,'donor'])) donlen[[j]] <- seqle(donmat[donmat[,'donor']==j,2])
Rgames> donlen
$bob
Run Length Encoding
  lengths: int [1:4] 3 2 2 3
  values : num [1:4] 1 5 8 12

$carol
Run Length Encoding
  lengths: int [1:3] 5 3 2
  values : num [1:3] 1 7 9

$alice
Run Length Encoding
  lengths: int [1:4] 1 3 3 3
  values : num [1:4] 1 3 7 11

因此,通过查看长度,我们看到“carol”有五年的序列。您可能希望使用lubridate从日期字符串中提取年份值。