簡體   English   中英

計算滿足另一個表中標准的行數 - R編程

[英]Count number of rows meeting criteria in another table - R PRogramming

我有兩個表,一個有房產列表,另一個有房產聯系人(即有人對他們將“聯系”房主的房產感興趣)。

示例“列表”表格如下:

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'天內為房產所做的聯系人數量。 輸出應該是添加到“聯系人”的“列表”的新列:

樣品('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'作為變量。 我無法找到在操作函數中完成所有這些操作的方法。

這是使用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

我不確定你的實際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

你可以使用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)]))

我不認為零結果可以通過過濾階段合理地傳遞(可以理解,目標通常是相反的)。 我不太確定'哪個'組件會對處理時間產生什么樣的影響,可能比使用'過濾'功能慢,但可能無關緊要。

要么:

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

使用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

我不確定我理解你的第二個問題要回答它。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM