[英]R: subsetting with respect to a vector
我试图弄清楚如何只对最后一列具有相同条目的矩阵行应用某个函数,但是到目前为止没有运气。
我的矩阵(我们将简称为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
软件包中可能有一些有用的plyr
,但是我无法使其工作。 任何建议,不胜感激!
更新资料
就我而言, fun1=min
。 问题同时发生了变化:在将数据按NAME
分组的同时,我想获取每个组中第1列的最小值,并保存找到最小值的整个行,如下所示:假设d1.1 < d2.1
和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
而不会损失其他列。 我尝试按照建议的方法处理mutate
和summarise
参数,但不断收到警告和错误(实际上我发现help()
一点都没有help()
)。
您可以尝试:
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
另一种办法是尝试summaryBy
从doBy
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))
我想我做到了!
library(dplyr)
df1 <- df %>%
group_by(NAMES) %>%
filter(df, X1 == min(X1))
返回的最小值,未删除任何数据。 我在另一个线程上找到了类似的答案。 如果存在多个最小值,它将具有返回所有行的问题,但这不是我的情况。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.