【问题标题】:Frequency of categorical values for different variables/cols in R?R中不同变量/列的分类值的频率?
【发布时间】:2013-11-12 14:06:49
【问题描述】:

我尝试汇总来自信号检测实验的数据来计算命中率、误报率等。

   Code Cond bf1 bf2 bf3 bf4 bm1 bm2 bm3 bm4
BAX-011    3  CR  FA HIT  FA  FR  CR  FA  FA

我的变量 bf1 到 bm3 是水平为(hit,fa,cr,fr) 的因子。

我想计算命中数,fa's ...for each 参与者(行),但包含变量子集(bf-items and bm-items)。最简单的方法是什么?

最后应该是这样的:

   Code Cond bf1 bf2 bf3 bf4 bm1 bm2 bm3 bm4 bf_hits bm_hits bf_fa ...
BAX-011    3  CR  FA HIT  FA  FR  CR  FA  FA       1       0     2 ...

【问题讨论】:

  • 类似这样的东西:sum(c("CR","FA","HIT","FA") == "HIT")
  • 谢谢!这对向量非常有效。但是我怎样才能为 data.frame 和我的所有参与者做到这一点呢?
  • 试试我的更新答案。

标签: r count aggregate rows


【解决方案1】:

如果我正确理解您的问题,您可能只需要从“reshape2”包中探索meltdcast。使用@zx8754 的示例数据,尝试以下操作:

library(reshape2)

### Make the data into a "long" format
dfL <- melt(df, id.vars=c("Code", "Cond"))

### Split the existing "variable" column. 
### Here's one way to do that.
dfL <- cbind(dfL, setNames(
  do.call(rbind.data.frame, strsplit(
    as.character(dfL$variable), "(?=\\d)", perl=TRUE)), 
  c("var", "time")))

### This is what the data now look like.
head(dfL)
#      Code Cond variable value var time
# 1 BAX-011    3      bf1    CR  bf    1
# 2 BAX-012    3      bf1    CR  bf    1
# 3 BAX-013    3      bf1    CR  bf    1
# 4 BAX-011    3      bf2    FA  bf    2
# 5 BAX-012    3      bf2    FA  bf    2
# 6 BAX-013    3      bf2   HIT  bf    2

### Use `dcast` to aggregate the data. 
### The default function is "length" which is what you're looking for.
dcast(dfL, Code + Cond ~ var + value, value.var="value")
# Aggregation function missing: defaulting to length
#      Code Cond bf_CR bf_FA bf_HIT bm_CR bm_FA bm_FR bm_HIT
# 1 BAX-011    3     1     2      1     1     2     1      0
# 2 BAX-012    3     1     2      1     0     2     1      1
# 3 BAX-013    3     1     1      2     0     2     1      1

从那里,您可以随时将mergecbind 相关列放在一起以获取完整的data.frame


更新

为避免被视为“reshape2”粉丝,这里有一个基本的 R 方法。我希望它也能说明我为什么在这种情况下走“reshape2”路线:

X <- grep("^bf|^bm", names(df))
df[X] <- lapply(df[X], as.character)
dfL <- cbind(dfL, setNames(
  do.call(rbind.data.frame, strsplit(
    as.character(dfL$ind), "(?=\\d)", perl=TRUE)),
  c("var", "time")))
dfL$X <- paste(dfL$var, dfL$values, sep ="_")
dfA <- aggregate(values ~ Code + Cond + X, dfL, length)
reshape(dfA, direction = "wide", idvar=c("Code", "Cond"), timevar="X")

【讨论】:

    【解决方案2】:

    试试这个:

    #dummy data
    df <- read.table(text="
    Code Cond bf1 bf2 bf3 bf4 bm1 bm2 bm3 bm4
    BAX-011    3  CR  FA HIT  FA  FR  CR  FA  FA
    BAX-012    3  CR  FA HIT  FA  FR  HIT  FA  FA
    BAX-013    3  CR  HIT HIT  FA  FR  HIT  FA  FA
    ", header=TRUE)
    
    #count HITs per bf bm
    df$bf_hit <- rowSums(df[,colnames(df)[grepl("bf",colnames(df))]]=="HIT")
    df$bm_hit <- rowSums(df[,colnames(df)[grepl("bm",colnames(df))]]=="HIT")
    
    #output
    df
    #Code Cond bf1 bf2 bf3 bf4 bm1 bm2 bm3 bm4 bf_hit bm_hit
    #1 BAX-011    3  CR  FA HIT  FA  FR  CR  FA  FA      1      0
    #2 BAX-012    3  CR  FA HIT  FA  FR HIT  FA  FA      1      1
    #3 BAX-013    3  CR HIT HIT  FA  FR HIT  FA  FA      2      1
    

    【讨论】:

    • 您的代码似乎计算了所有行中的 HITS 而不仅仅是一行。至少如果我将它应用到具有多行/参与者的数据框,它会这样做。
    • @zx8754, Another job for "reshape2" :-)
    • @user2983485 如果有帮助,请点赞或接受作为答案。
    • @AnandaMahto 可能不是学习 R 的最佳方法,但我更喜欢带有基本 R 包的解决方案。如果太复杂,我会寻找合适的包。
    • @zx8754,查看我的更新。如果您查看我的个人资料,尤其是我回答了哪些问题dealing with reshaping questions,我通常会提出很多基本的 R 解决方案。
    猜你喜欢
    • 2018-05-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多