【问题标题】:R: subsetting with respect to a vectorR:关于向量的子集
【发布时间】:2014-10-01 08:01:33
【问题描述】:

我试图弄清楚如何将某个函数仅应用于最后一列具有相同条目的矩阵的行,但直到现在还没有运气。

我的矩阵(我们将简称为 matrix 并假设它是 5x4)如下所示:

d1.1   d1.2   d1.3   NAME1 
d2.1   d2.2   d2.3   NAME1 
d3.1   d3.2   d3.3   NAME2 
d4.1   d4.2   d4.3   NAME3
d5.1   d5.2   d5.3   NAME2`

我想对同名的行进行汇总统计fun1,以便得到一个看起来像这样的最终矩阵:

fun1(d1.1, d2.1)   fun1(d1.2, d2.2)   fun1(d1.3, d2.3)   NAME1
fun1(d3.1, d5.1)   fun1(d3.2, d5.2)   fun1(d3.3, d5.3)   NAME2
d4.1               d4.2               d4.3               NAME3.

fun1 也可以在“单”行上执行,即

fun1(d1.1, d2.1)   fun1(d1.2, d2.2)   fun1(d1.3, d2.3)   NAME1
fun1(d3.1, d5.1)   fun1(d3.2, d5.2)   fun1(d3.3, d5.3)   NAME2
fun1(d4.1)         fun1(d4.2)         fun1(d4.3)         NAME3.

我试过了

sapply(subset(matrix[,1:3], as.character(matrix[,4])==as.character(listofnames)), fun1)

但当然它不起作用。当前的问题在于子集as.character(matrix[,4])==as.character(listofnames),因为这两个对象具有不同的尺寸,但我确信这不是唯一的。

我试图寻找类似的问题,但我只是通过指定的(数字)条件 (>3) 或模式(每组 7 个有序条目)找到子集。没有运气因素或性格。

我想plyr 包中可能有一些有用的东西,但我无法让它工作。任何建议都非常感谢!

更新

就我而言,fun1=min。问题同时发生了变化:在保持数据按NAME 分组的同时,我想获取每组中第 1 列的最小值并保存找到最小值的整行,如下所示:假设@987654332 @ 和d5.1 < d3.1,然后是矩阵

d1.1   d1.2   d1.3   NAME1 
d2.1   d2.2   d2.3   NAME1 
d3.1   d3.2   d3.3   NAME2 
d4.1   d4.2   d4.3   NAME3
d5.1   d5.2   d5.3   NAME2

应该变成

d1.1   d1.2   d1.3   NAME1 
d4.1   d4.2   d4.3   NAME3
d5.1   d5.2   d5.3   NAME2

不会丢失其他列。 我尝试按照建议使用mutatesummarise 参数,但不断收到警告和错误(实际上我发现help() 一点帮助都没有)。

【问题讨论】:

  • @jejroje 如果列是不同的classes,将matrix 转换为data.frame 可能会更好
  • 我更新了帖子。当您执行 summarise_eachsummarise 时,每个分组变量的输出将为 1 行。因此,如果您在每一行中都有 cmets 并希望保留它,summarise_each 之后的一种可能性是将left_join 与原始数据集一起使用,或者只使用mutate_each。目前尚不清楚您的预期输出是什么。

标签: r matrix dataframe subset


【解决方案1】:

你可以试试:

library(dplyr)
dfSelectSummary <- df %>% 
              group_by(name) %>% 
             summarise_each(funs(mean=mean(., na.rm=TRUE), sd=sd(., na.rm=TRUE),
             median=stats::median(., na.rm=TRUE)), starts_with("X"))

dfSelectSummary[,1:4]
#Source: local data frame [3 x 4]

#   name X1_mean  X2_mean  X3_mean
#1 NAME1   4.250 3.333333 4.888889
#2 NAME2   5.375 4.555556 6.000000
#3 NAME3   6.000 8.000000 9.000000

或者你可以使用data.table

library(data.table)
DT <- data.table(df, key='name')
nm1 <- colnames(DT[, as.list(summary(X1[!is.na(X1)])), by=name])[-1]
DTSummary <- DT[,  c(Var=list(nm1),
    lapply(.SD, function(x) summary(x[!is.na(x)]))), by=name]

head(DTSummary,8)
#    name     Var    X1    X2     X3    X4    X5
#1: NAME1    Min.  1.00 0.000  0.000 3.000  0.00
#2: NAME1 1st Qu.  2.00 2.000  1.000 3.750  3.25
#3: NAME1  Median  3.50 3.000  6.000 7.500  5.00
#4: NAME1    Mean  4.25 3.333  4.889 6.375  5.00
#5: NAME1 3rd Qu.  6.00 5.000  8.000 8.250  7.25
#6: NAME1    Max. 10.00 7.000 10.000 9.000 10.00
#7: NAME2    Min.  0.00 0.000  0.000 1.000  1.00
#8: NAME2 1st Qu.  3.75 4.000  4.000 3.000  4.25

另一种选择是从doBy 尝试summaryBy

library(doBy)
 summaryBy(.~name, data=df,
    FUN=function(x) c(mean=mean(x, na.rm=TRUE), var= var(x, na.rm=TRUE),
                    median=median(x, na.rm=TRUE)))

如果您有numeric 名称列,则可能不需要转换matrix

 m1 <- as.matrix(cbind(name=as.numeric(df$name), df[,-1]))
 by(m1[,-1], m1[,1], FUN=summary)

数据

set.seed(45)
df <- data.frame(name=sample(paste0("NAME", 1:3),20, replace=TRUE),
        matrix(sample(c(NA, 0:10), 20*5, replace=TRUE), ncol=5))

更新

如果您需要long 表单中的结果并希望保留comments 列,您可以使用mutate_each

 df1 <- df %>% 
           group_by(name) %>% 
           mutate_each(funs(min=min(., na.rm=TRUE)), starts_with("X"))

 colnames(df1)[2:6] <- paste0("Min", colnames(df1)[2:6])
 head(df1,3)
 #Source: local data frame [3 x 7]
 #Groups: name

 #   name MinX1 MinX2 MinX3 MinX4 MinX5 Comments
 #1 NAME2     0     0     0     1     1     Fair
 #2 NAME1     1     0     0     3     0      Bad
 #3 NAME1     1     0     0     3     0     Good

新数据

  set.seed(45)
  df <- data.frame(name=sample(paste0("NAME", 1:3),20, replace=TRUE),
          matrix(sample(c(NA, 0:10), 20*5, replace=TRUE), ncol=5), 
             Comments=sample(c("Good", "Fair", "Bad", "ugly"), 20, replace=TRUE))

【讨论】:

  • 谢谢@akrun。我想知道,summarise_each 函数不能在输出中“保存”其他变量,可以吗?我在每个名称旁边都有一些 cmets,我的摘要统计是 min,所以我想知道除了值和名称之外,我是否可以获得与适当值对应的 cmets。
  • @jeiroje 这些 cmets 是每行独有的还是有重复的?
  • 谢谢@akrun。 cmets 既独特又重复,但如果我得到独特的,那么我可以掩盖它们并获得重复的。我也更新了问题,因为问题同时发生了变化。
【解决方案2】:

我想我做到了!

library(dplyr)

df1 <- df %>%
       group_by(NAMES) %>%
       filter(df, X1 == min(X1))

返回最小值,未删除任何数据。 我在另一个线程上找到了类似的答案。如果存在多个最小值,它会返回所有行,但这不是我的情况。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-27
    • 1970-01-01
    • 1970-01-01
    • 2021-06-16
    相关资源
    最近更新 更多