Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/r/81.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
R 计算项目在多个列中出现的次数_R_Dataframe - Fatal编程技术网

R 计算项目在多个列中出现的次数

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

我想读取一个表并创建另一个表,该表计算一个唯一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, 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