这个问题听起来可能与其他问题相似,但我希望它与众不同。 我想获取一个特定的值列表,并计算它们出现在另一个值列表中的频率,其中非出现值被重新调整为“0”。
我有一个数据框(df1),其中包含以下值:
Items <- c('Carrots','Plums','Pineapple','Turkey')
df1<-data.frame(Items)
>df1
Items
1 Carrots
2 Plums
3 Pineapple
4 Turkey
第二个数据框(df2),其中包含一个名为“Thing”的列:
> head(df2,n=10)
ID Date Thing
1 58150 2012-09-12 Potatoes
2 12357 2012-09-28 Turnips
3 50788 2012-10-04 Oranges
4 66038 2012-10-11 Potatoes
5 18119 2012-10-11 Oranges
6 48349 2012-10-14 Carrots
7 23328 2012-10-16 Peppers
8 66038 2012-10-26 Pineapple
9 32717 2012-10-28 Turnips
10 11345 2012-11-08 Oranges
我知道“土耳其”这个词只出现在df1而不是df2中。我想返回df1中出现的频率表或项目数,df2中出现的项目,并返回“0”表示土耳其的数量。
如何使用另一个值中的值汇总数据框列的值?我得到的最接近的是:
df2%>% count (Thing) %>% filter(Thing %in% df1$Items,)
但是这会返回在df1和df2之间过滤的项目列表,因此“土耳其”被排除在外。太近了!
> df2%>% count (Thing) %>% filter(Thing %in% df1$Items,)
# A tibble: 3 x 2
Thing n
<fctr> <int>
1 Carrots 30
2 Pineapple 30
3 Plums 38
我希望我的输出看起来像这样:
1 Carrots 30
2 Pineapple 30
3 Plums 38
4 Turkey 0
我对R很新,对dplyr来说是全新的。
答案 0 :(得分:0)
我一直都在使用这种东西。我确信有一种更精明的编码方式,但这就是我得到的:
item <- vector()
count <- vector()
items <- list(unique(df1$Items))
for (i in 1:length(items)){
item[i] <- items[i]
count[i] <- sum(df2$Thing == item)
}
df3 <- data.frame(cbind(item, count))
希望这有帮助!
答案 1 :(得分:0)
Stephen的解决方案稍作修改,在count [i]行末尾将[i]添加到项目中。见下文:
item <- vector()
count <- vector()
for (i in 1:length(unique(Items))){
item[i] <- Items[i]
count[i]<- sum(df2$Thing == item[i])
}
df3 <- data.frame(cbind(item, count))
> df3
item count
1 Carrots 30
2 Plums 38
3 Pineapple 30
4 Turkey 0
答案 2 :(得分:0)
dplyr 会丢弃0个计数行,并且您会增加一个复杂性,即Thing
的可能类别在您的两个数据集之间有所不同。
如果您将因子级别从df1
添加到df2
,则可以使用 tidyr 中的complete
,这是{{3}的常用方式}。
我正在使用名为df1
的包 forcats 中的便捷函数将因子级别从df2
添加到fct_expand
。
library(dplyr)
library(tidyr)
library(forcats)
df2 %>%
mutate(Thing = fct_expand(Thing, as.character(df1$Item) ) ) %>%
count(Thing) %>%
complete(Thing, fill = list(n = 0) ) %>%
filter(Thing %in% df1$Items,)
答案 3 :(得分:0)
另一种方法是首先汇总df2
,然后与df1
进行正确联接(以选择df1
的所有行),并将NA
替换为零。< / p>
library(dplyr)
df2 %>%
count(Thing) %>%
right_join(unique(df1), by = c("Thing" = "Items")) %>%
mutate(n = coalesce(n, 0L))
# A tibble: 4 x 2 Thing n <chr> <int> 1 Carrots 1 2 Plums 0 3 Pineapple 1 4 Turkey 0 Warning message: Column `Thing`/`Items` joining factors with different levels, coercing to character vector
data.table
中的相同方法:
library(data.table)
setDT(df2)[, .N, by = Thing][unique(setDT(df1)), on = .(Thing = Items)][is.na(N), N := 0L][]
Thing N 1: Carrots 1 2: Plums 0 3: Pineapple 1 4: Turkey 0
请注意,在两个实现中,unique(df1)
用于避免在连接后出现意外的重复行。
如果df2
很大且df1
只包含少量Items
,则首先加入然后合并可能更有效:
library(dplyr)
df2 %>%
right_join(unique(df1), by = c("Thing" = "Items")) %>%
group_by(Thing) %>%
summarise(n = sum(!is.na(ID)))
# A tibble: 4 x 2 Thing n <chr> <int> 1 Carrots 1 2 Pineapple 1 3 Plums 0 4 Turkey 0 Warning message: Column `Thing`/`Items` joining factors with different levels, coercing to character vector
data.table syntax
中的相同内容:
library(data.table)
setDT(df2)[unique(setDT(df1)), on = .(Thing = Items)][, .(N = sum(!is.na(ID))), by = Thing][]
Thing N 1: Carrots 1 2: Plums 0 3: Pineapple 1 4: Turkey 0