我想在Id_no上折叠下面的数据集,但只有在其他变量满足某些条件并计算特殊的折叠变量时才会折叠。
df <- structure(list(Id_no = structure(c(1L, 1L, 1L, 2L, 2L, 3L), .Label = c("n1",
"n2", "n3"), class = "factor"), Band = structure(c(1L, 2L, 3L,
1L, 2L, 1L), .Label = c("Band 1", "Band 2", "Band 3"), class = "factor"),
median = c(252, 191, 107, 130.5, 61.5, 217), sample_size = c(19L,
20L, 1L, 20L, 12L, 1544L)), .Names = c("Id_no", "Band", "median",
"sample_size"), class = "data.frame", row.names = c(NA, -6L))
> df
Id_no Band median sample_size
1 n1 Band 1 252.0 19
2 n1 Band 2 191.0 20
3 n1 Band 3 107.0 1
4 n2 Band 1 130.5 20
5 n2 Band 2 61.5 12
6 n3 Band 1 217.0 1544
崩溃变量是Band 1中位数与2和3之间平均中位数之比。
这将针对Id_no计算,其实际上具有B1和B2或B3中的至少一个的条目。
此外,仅当样本量≥10时才应考虑B2和B3中位数。
我正在寻找的结果表是:
Id_no b1_vs_rest
1 n1 1.32
2 n2 2.12
第一步可能是删除样本量不符合最小值的情况:
df <- subset(df, sample_size >=10)
答案 0 :(得分:1)
这是一个使用dplyr
和if...else
构造来改变条件输出的解决方案。根据你的问题(而不是你预期的结果),我假设你想要乐队1的中位数与乐队2和3的中位数的平均比例,如果你有三个。
d2 <- df %>%
filter(sample_size >= 10) %>%
group_by(Id_no) %>%
summarise(b1_vs_rest = if(any(Band == "Band 2") & any(Band == "Band 3")) {
median[Band == "Band 1"] / (mean(c(median[Band == "Band 2"], median[Band == "Band 3"])))
} else if(any(Band == "Band 2")) {
median[Band == "Band 1"] / median[Band == "Band 2"]
} else if(any(Band == "Band 3")) {
median[Band == "Band 1"] / median[Band == "Band 3"]
} else {
NA
}) %>%
filter(!is.na(b1_vs_rest))
结果:
> d2
# A tibble: 2 × 2
Id_no b1_vs_rest
<fctr> <dbl>
1 n1 1.319372
2 n2 2.121951
答案 1 :(得分:1)
使用dplyr
的一种方法:
library(dplyr)
res <- df %>% group_by(Id_no) %>%
filter(sample_size >= 10) %>%
summarise(b1_vs_rest=median[Band == "Band 1"]/mean(median[Band != "Band 1"])) %>%
filter(!is.nan(b1_vs_rest))
注意:
dplyr
,首先filter
仅保留sample_size
大于或等于10
的行。 group_by
Id_no
和summarise
计算每个Id_no
选择分子median
Band == "Band 1"
和"Band 1"
的比率所有其他乐队的中位数。"Band 2"
和mean
都不存在,那么NaN
将返回NaN
,结果也将是filter
。因此,我们NaN
再次仅保留非print(res)
### A tibble: 2 x 2
## Id_no b1_vs_rest
## <fctr> <dbl>
##1 n1 1.319372
##2 n2 2.121951
值。使用您的数据的结果符合预期:
{{1}}
答案 2 :(得分:1)
以下是使用data.table
的选项。转换&#39; data.frame&#39;到&#39; data.table&#39; (setDT(df)
),重塑长期&#39;广泛的&#39; (dcast
),删除NA行(na.omit
),将.SDcols
指定为&#39; Band&#39;列,将第一列(.SD[[1]]
)除以其他列(Reduce(`+`, ...)
)的总和,以获得预期的输出。
library(data.table)#1.9.7+
na.omit(dcast(setDT(df)[sample_size >= 10], Id_no~Band, value.var = "median"))[,
.(Id_no, b1_vs_rest = .SD[[1]]/Reduce(`+`, .SD[, -1, with = FALSE])) , .SDcols = -1]
# Id_no b1_vs_rest
#1: n1 1.319372
#2: n2 2.121951