R 计算项目在多个列中出现的次数
我想读取一个表并创建另一个表,该表计算一个唯一ID在多个特定列中出现的次数 例如,我有一个表,其中每一行显示一个事务,用户ID标识每个人的角色R 计算项目在多个列中出现的次数,r,dataframe,R,Dataframe,我想读取一个表并创建另一个表,该表计算一个唯一ID在多个特定列中出现的次数 例如,我有一个表,其中每一行显示一个事务,用户ID标识每个人的角色 buyer <- c("A", "A", "B", "A", "B", "C") seller <- c("C", "B", "C", "B", "C", "A") negotiator <- c("B", "C", "D", "D", "A", "B") df <- data.frame(buyer, sel
buyer <- c("A", "A", "B", "A", "B", "C")
seller <- c("C", "B", "C", "B", "C", "A")
negotiator <- c("B", "C", "D", "D", "A", "B")
df <- data.frame(buyer, seller, negotiator)
df
# buyer seller negotiator
# 1 A C B
# 2 A B C
# 3 B C D
# 4 A B D
# 5 B C A
# 6 C A B
我是否需要创建不同的数据帧,然后进行合并?我将使用
数据。表
:
更新灵感来源于MrFlick
您可以将fun.aggregate=length
作为参数添加到dcast
以抑制警告消息。如果您希望将该列命名为id
,则可以将value.name=“id”
作为参数添加到melt
原创性的,较长的回答
setDT(df)
outDT您可以先将数据熔化,然后将其制成表格。比如说
dd<-reshape2::melt(df,0)
xtabs(~value+variable,dd)
# variable
# value buyer seller negotiator
# A 3 1 1
# B 2 2 2
# C 1 3 1
# D 0 0 2
dd这里有一个仅使用基本R的解决方案(可能比其他方法慢):
lst这里的R向导太多了
下面是我的简单解决方案,使用basic R和ddply
(创建“count group by”表)和merge
(执行外部联接)
#为买家数量创建数据框
dfBuyer 0传递给什么?有趣的是,我以前没有想过melt(df,0)
。)如果没有restrape2
且df
列为字符类型,则可能带有(setNames(stack(df),c(“id”,“as”)),xtabs(~id+as))
@MichaelChirico,0将转到id.vars
参数。在这种情况下,除了行索引本身之外,没有其他变量表示每一行。这是数据表中的一个错误。你能详细说明一下它是如何工作的吗?@MichaelChirico它似乎做了与你在回答中做的相同的事情:melt(df,measure.vars=names(df))==melt(df,0)
有点类似的一行:do.call(cbind,lapply(df,function(L)table)(factor(L,levels)(unlist(df);)))
@MaratTalipov:好主意,使用unlist(df)
创建所有可能的值,以便使用cbind
而不是merge
+1@MaratTalipov:你应该把你自己的答案贴在我的邮箱上;)@DigeMail我也尝试使用base R。请在下面评论我的解决方案。您的解决方案很好,但它是针对您的特定问题“硬编码”的。例如,如果输入数据框具有不同的列名或列数,则必须重写代码。我建议研究@digEmAll的解决方案,它的逻辑与您的解决方案相同,但更具普遍性。PS:'base R'代码不需要任何额外的包,而您的代码需要包'plyr'(如果我没记错的话)。是的,正如@MaratTalipov正确地说的,这与我的解决方案非常相似;主要区别在于,我的代码更通用,如果向初始data.frame添加一个新列,则无需更改任何内容。事实上,我使用lappy
对每个列执行计数,并使用Reduce
多次调用merge。您还使用了plyr
包中的ddply
,因此严格来说,它不是base R。无论如何,我看不出您的方法有任何特殊问题;)
library(data.table)
setDT(df)
dcast(melt(df, measure.vars = names(df)), value ~ variable)
# value buyer seller negotiator
# 1: A 3 1 1
# 2: B 2 2 2
# 3: C 1 3 1
# 4: D 0 0 2
setDT(df)
outDT <- data.table(id = unique(unlist(df)))
invisible(
sapply(names(df), function(jj)
outDT[df[ , .N, by = jj],
#set the name you desire by pasting;
# could use a regex or substr to
# for the first letter capital if need be
(jj2 <- paste0("as", jj)) := i.N,
#merge id to the count column
on = c(id = jj)
clean-up: missed observations were NA, set to 0
][is.na(get(jj2)), (jj2) := 0])
)
dd<-reshape2::melt(df,0)
xtabs(~value+variable,dd)
# variable
# value buyer seller negotiator
# A 3 1 1
# B 2 2 2
# C 1 3 1
# D 0 0 2
lst <- lapply(names(df), function(col) as.data.frame(table(df[[col]]),responseName=col))
mergeAll <- function(x,y) merge(x,y,all=TRUE)
res <- Reduce(f=mergeAll, lst)
names(res)[1] <- 'id'
res[is.na(res)] <- 0
> res
id buyer seller negotiator
1 A 3 1 1
2 B 2 2 2
3 C 1 3 1
4 D 0 0 2
# Create data frame for buyer count
dfBuyer <- ddply(df, c("buyer"), summarise, count=length(seller))
colnames(dfBuyer) <- c("id", "asBuyer")
dfBuyer
# id asBuyer
# 1 A 3
# 2 B 2
# 3 C 1
# Create data frame for seller count
dfSeller <- ddply(df, c("seller"), summarise, count=length(buyer))
colnames(dfSeller) <- c("id", "asSeller")
dfSeller
# id asSeller
# 1 A 1
# 2 B 2
# 3 C 3
# Create data frame for negotiator count
dfNegotiator <- ddply(df, c("negotiator"), summarise, count=length(seller))
colnames(dfNegotiator) <- c("id", "asNegotiator")
dfNegotiator
# id asNegotiator
# 1 A 1
# 2 B 2
# 3 C 1
# 4 D 2
# merge() apparently can merge only two dataframes at a time,
# so to merge three dataframes, merge the first two and then
# the third. Use "all=TRUE" to perform outer join.
# Merge buyer and seller
dfBuyerSellerMerged <- merge(x=dfBuyer, y=dfSeller, by="id", all=TRUE)
# Merge buyer and seller and negotiator
dfBuyerSellerNegotiatorMerged <- merge(x=dfBuyerSellerMerged, y=dfNegotiator, by="id", all=TRUE)
dfBuyerSellerNegotiatorMerged
# id asBuyer asSeller asNegotiator
# 1 A 3 1 1
# 2 B 2 2 2
# 3 C 1 3 1
# 4 D NA NA 2
# Remove NAs.
dfBuyerSellerNegotiatorMerged[is.na(dfBuyerSellerNegotiatorMerged)] <- 0
dfBuyerSellerNegotiatorMerged
# id asBuyer asSeller asNegotiator
# 1 A 3 1 1
# 2 B 2 2 2
# 3 C 1 3 1
# 4 D 0 0 2