计算满足另一个表中标准的行数 - R编程

时间:2015-06-22 05:42:39

标签: r

我有两个表,一个有房产列表,另一个有房产的联系人(即有人对他们将“联系”房主的房产感兴趣)。

以下示例“列表”表:

listings <- data.frame(id = c("6174", "2175", "9176", "4176", "9177"), city = c("A", "B", "B", "B" ,"A"), listing_date = c("01/03/2015", "14/03/2015", "30/03/2015", "07/04/2015", "18/04/2015"))
listings$listing_date <- as.Date(listings$listing_date, "%d/%m/%Y")

listings
#    id city listing_date
#1 6174    A   01/03/2015
#2 2175    B   14/03/2015
#3 9176    B   30/03/2015
#4 4176    B   07/04/2015
#5 9177    A   18/04/2015

以下示例“联系人”表格:

contacts <- data.frame (id = c ("6174", "6174", "6174", "6174", "2175", "2175", "2175", "9176", "9176", "4176", "4176", "9177"), contact_date = c("13/03/2015","14/04/2015", "27/03/2015", "13/04/2015", "15/03/2015", "16/03/2015", "17/03/2015", "30/03/2015", "01/06/2015", "08/05/2015", "09/05/2015", "23/04/2015" ))

contacts$contact_date <- as.Date(contacts$contact_date, "%d/%m/%Y")
contacts
#     id contact_date
#1  6174   2015-03-13
#2  6174   2015-04-14
#3  6174   2015-03-27
#4  6174   2015-04-13
#5  2175   2015-03-15
#6  2175   2015-03-16
#7  2175   2015-03-17
#8  9176   2015-03-30
#9  9176   2015-06-01
#10 4176   2015-05-08
#11 4176   2015-05-09
#12 9177   2015-04-23

问题 1.我需要在上市后的第x天计算一个房产的联系人数量。输出应该是添加到“listing”的新列:#contacts:

样本('x'= 30天)

listings
#    id city listing_date ngs
#1 6174    A   2015-03-01   2
#2 2175    B   2015-03-14   3
#3 9176    B   2015-03-30   1
#4 4176    B   2015-04-07   0
#5 9177    A   2015-04-18   1

我用for循环完成了这个;实时数据的速度很慢:

n <- nrow(listings)
mat <- vector ("integer", n)
for (i in 1:n) {  
  mat[i] <- nrow (contacts[contacts$id==listings[i,"id"] & as.numeric (contacts$contact_date - listings[i,"listing_date"]) <=30,])
}
listings$ngs <- mat
  1. 我需要通过操作函数准备一个#contacts vs days的直方图,'x'作为变量。我无法找到在操作函数中完成所有这些操作的方法。

5 个答案:

答案 0 :(得分:2)

以下是使用data.table 滚动连接

的可能解决方案
library(data.table)

# key `listings` by proper columns in order perform the binary join
setkey(setDT(listings), id, listing_date)

# Perform a binary rolling join while extracting matched icides and counting them
indx <- data.table(listings[contacts, roll = 30, which = TRUE])[, .N, by = V1]

# Joining back to `listings` by proper rows while assigning the counts by reference
listings[indx$V1, ngs := indx$N]
#      id city listing_date ngs
# 1: 2175    B   2015-03-14   3
# 2: 4176    B   2015-04-07  NA
# 3: 6174    A   2015-03-01   2
# 4: 9176    B   2015-03-30   1
# 5: 9177    A   2015-04-18   1

答案 1 :(得分:1)

我不确定您的实际id值是否是因素,但我会从制作这些数字开始。使用它们作为因素会导致问题:

listings$id <- as.numeric(as.character(listings$id))
contacts$id <- as.numeric(as.character(contacts$id))

然后,策略是计算每个联系人的“自上市以来的天数”值,并将其添加到您的contacts data.frame。然后,汇总这个新的data.frame(在您的示例中,30天内的联系人总数),然后将得到的计数合并回原始数据。

contacts$ngs <- contacts$contact_date - listings$listing_date[match(contacts$id, listings$id)]
a <- aggregate(ngs ~ id, data = contacts, FUN = function(x) sum(x <= 30))
merge(listings, a)
#     id city listing_date ngs
# 1 2175    B   2015-03-14   3
# 2 4176    B   2015-04-07   0
# 3 6174    A   2015-03-01   2
# 4 9176    B   2015-03-30   1
# 5 9177    A   2015-04-18   1

答案 2 :(得分:1)

您可以使用dplyr包。首先合并数据:

all.data <- merge(contacts,listings,by = "id")

设定目标天数:

number.of.days <- 30

然后按ID(group_by)收集数据,排除不在时间范围内的结果(过滤器)并计算出现次数/行数(汇总)。

result <- all.data %>% group_by(id) %>% filter(contact_date > listing_date + number.of.days) %>% summarise(count.of.contacts = length(id))

我认为有很多方法可以解决,但我发现dplyr在很多情况下都非常有用。

编辑:

抱歉,应该多考虑一下。这有用吗,

result <- all.data %>% group_by(id,city,listing_date) %>% summarise(ngs = length(id[which(contact_date < listing_date + number.of.days)]))

我不认为零结果可以通过过滤阶段合理地传递(可以理解,目标通常是相反的)。我不太确定&#39;哪个&#39;哪个&#39;组件将具有处理时间,可能比使用&#39;过滤器慢?功能,但可能无关紧要。

答案 3 :(得分:1)

或者:

indx <- match(contacts$id, listings$id)
days_since <- contacts$contact_date - listings$listing_date[indx]
n <- with(contacts[days_since <= 30, ], tapply(id, id, length))
n[is.na(n)] <- 0
listings$n <- n[match(listings$id, names(n))]

它类似于托马斯的答案,但使用tapplymatch代替aggregatemerge

答案 4 :(得分:1)

使用dplyr解决您的第一个问题:

left_join(contacts, listings, by = c("id" = "id")) %>%
filter(abs(listing_date - contact_date) < 30) %>%
group_by(id) %>% summarise(cnt = n()) %>%
right_join(listings)

输出是:

    id      cnt city    listing_date
1   6174    2   A        2015-03-01
2   2175    3   B        2015-03-14
3   9176    1   B        2015-03-30
4   4176    NA  B        2015-04-07
5   9177    1   A        2015-04-18

我不确定我理解你的第二个问题要回答它。