如何将CSV列范围添加到表中

时间:2016-07-03 02:44:00

标签: r lapply

我正在使用R并读取CSV文件来汇总文件中的值为零的列组,以及是否有过敏反应。这个文件包含538个变量,最初这些变量是整数,所以我将所有整数转换为因子变量,这解决了我的目的。但是我只能使用表函数来汇总所有因子列的值,但是我需要对列进行分组并将它们应用于表函数以进行逐组汇总。在这方面有谁可以帮助我?

我的代码如下....

egg1 <-read.csv("egg.csv",header = TRUE)

str(egg1)

egg1[sapply(egg1, is.integer)] <- lapply(egg1[sapply(egg1, is.integer)], as.factor)

lapply(egg1, function(egg1) {
   if (is.factor(egg1)) return(table(egg1))
  })

这里我在表中希望按组传递CSV文件的变量范围。 请查看我的示例CSV,其中包含3个我已着色的组,以便更好地理解。 Q1:我想分别计算剂量1,剂量2和剂量3的是/否(1/0)的分布,其中每种都列出3种症状。 Q2:然后比较所有3种剂量的症状。

表通过显示所有列的摘要很好,但我需要分组总结。

sample data

2 个答案:

答案 0 :(得分:0)

正如@alistaire所说,我们错过了一个可重复的例子,但也许这会充分猜测结构和你的意图。

我会制作一些数据,我希望它能让你想起你的真实数据。而不是factor,我认为您应该能够使用logical,因为您说感兴趣的列是0或1之一。

set.seed(4)
egg1 <- data.frame(
  v1 = sample(0:1, size=20, replace=TRUE),
  v2 = sample(0:1, size=20, replace=TRUE),
  v3 = sample(c('a','b','c'), size=20, replace=TRUE),
  v4 = sample(0:1, size=20, replace=TRUE),
  stringsAsFactors = FALSE)
str(egg1)
# 'data.frame': 20 obs. of  4 variables:
#  $ v1: int  1 0 0 0 1 0 1 1 1 0 ...
#  $ v2: int  1 1 1 0 1 1 0 1 1 1 ...
#  $ v3: chr  "c" "a" "b" "a" ...
#  $ v4: int  1 0 1 1 0 1 0 1 1 1 ...

(我包括v3,假设并非所有列都是0/1布尔值。)

这是第一次尝试:

sapply(Filter(is.numeric, egg1),
       function(egg) table(egg == 1))
#       v1 v2 v4
# FALSE  9  7 10
# TRUE  11 13 10

不幸的是,它有一个轻微的缺陷:它假设所有结果都具有相同的长度,但并非总是如此:

set.seed(105966)
egg1 <- data.frame(
  v1 = sample(0:1, size=20, replace=TRUE),
  v2 = sample(0:1, size=20, replace=TRUE),
  v3 = sample(c('a','b','c'), size=20, replace=TRUE),
  v4 = sample(0:1, size=20, replace=TRUE),
  stringsAsFactors = FALSE)
sapply(Filter(is.numeric, egg1),
       function(egg) table(egg == 1))
# $v1
# FALSE  TRUE 
#     9    11 
# $v2
# FALSE  TRUE 
#     8    12 
# $v4
# TRUE 
#   20 

(也就是说,它返回一个列表,因为并非所有返回的元素都是长度为2:v4全部为1。)修复是为了确保您始终至少计算每个级别中的一个,然后确保在结果中计算:

sapply(Filter(is.numeric, egg1),
       function(egg) table(c(TRUE, FALSE, egg == 1)) - 1)
#       v1 v2 v4
# FALSE  9  8  0
# TRUE  11 12 20

答案 1 :(得分:0)

使用屏幕截图示例,请考虑重塑数据框。首先,melt()剂量症状列从宽到长,然后dcast()将no / yes迁移到不同的列中。您甚至可以将 dose_symp 列拆分为两个分组的 dose symp 字段:

library(reshape2)

df <- read.csv("Input.csv", stringsAsFactors = FALSE)

# MELT (LEAVING OUT TIME COLS)
mdf <- melt(df[!grepl("time", names(df))], id.vars = c("id", "DOB", "weight"), 
            variable.name = "symp_type")
mdf$key <- 1    
# CAST (FOR NO/YES COLUMNS, SUMMED ON KEY)
mdf <- dcast(mdf, id + DOB + weight + symp_type ~ value, sum, value.var = "key")

# UPDATE COLUMNS
names(mdf)[5:6] <- c("no", "yes")

mdf$symp_type <- as.character(mdf$symp_type)
mdf$dose <- sapply(strsplit(as.character(mdf$symp_type),"_"), "[", 1)
mdf$symp <- sapply(strsplit(as.character(mdf$symp_type),"_"), "[", 2)
mdf$symp_type <- NULL

# GROUP AGGREGATION (DATA REPEATS DUE TO REPLICATED DATA IN SAMPLE)
aggdf <- aggregate(.~symp, mdf[c("symp", "no", "yes")], FUN = sum)
aggdf
#    symp no yes
# 1 symp1 18  12
# 2 symp2 18  12
# 3 symp3 18  12

aggdf <- aggregate(.~dose, mdf[c("dose", "no", "yes")], FUN = sum)
aggdf
#    dose no yes
# 1 dose1 18  12
# 2 dose2 18  12
# 3 dose3 18  12

aggdf <- aggregate(.~symp + dose, mdf[c("symp", "dose", "no", "yes")], FUN = sum)
aggdf
#    symp  dose no yes
# 1 symp1 dose1  6   4
# 2 symp2 dose1  6   4
# 3 symp3 dose1  6   4
# 4 symp1 dose2  6   4
# 5 symp2 dose2  6   4
# 6 symp3 dose2  6   4
# 7 symp1 dose3  6   4
# 8 symp2 dose3  6   4
# 9 symp3 dose3  6   4