我希望对“ Y”列中任何字符相同的“ M”列中的值求和,因此,如果我的数据框看起来像这样:
X M.1 M.2 M.3 Y.1 Y.2 Y.3
K3 21 6 11 L N X
K8 31 1 29 N
K2 8 0 2 L Q Z
我想得到这个输出数据帧:
Y M.1 M.2 M.3
L 29 6 13
N 52 7 40
Q 8 0 2
X 21 6 11
如果可以将X列中包含“ Y”列中特定字符的所有值都包含到一列中,则奖励,如下所示:
Y M.1 M.2 M.3 X.all
L 29 6 13 K3,K2
N 52 7 40 K3,K8
Q 8 0 2 K2
X 29 6 13 K3
到目前为止,使用下面的aggregate()函数,我可以分别在“ Y”列中获取每个值的总和,但是希望有更好的方法来制作一个将所有总和加在一起的全新数据框
aggregate(cbind(df$M.1) ~ df$Y.1, data = df, sum)
非常感谢您的帮助!
答案 0 :(得分:1)
如果您想使用try{} catch(){}
函数,则可以分几步进行一些争论。我将其分解以查看中间结果。
关于缺失值:由您决定。您没有tidyverse
数据,因此当我用dput
作为文本读取数据时,空格将自动转换为readr::read_table2
。在这里,我保留了那些缺失的值。
因此,首先,NA
为您提供长形数据框,首先在单个列中包含tidyr::gather
,等等:
Y.1
第二library(dplyr)
library(tidyr)
df %>%
gather(key, value = Y, Y.1:Y.3) %>%
head()
#> # A tibble: 6 x 6
#> X M.1 M.2 M.3 key Y
#> <chr> <int> <int> <int> <chr> <chr>
#> 1 K3 21 6 11 Y.1 L
#> 2 K8 31 1 29 Y.1 N
#> 3 K2 8 0 2 Y.1 L
#> 4 K3 21 6 11 Y.2 N
#> 5 K8 31 1 29 Y.2 <NA>
#> 6 K2 8 0 2 Y.2 Q
将gather
和Y
s分为两列:
M
然后,您可以分组,使用粘贴的字符串(例如df %>%
gather(key, value = Y, Y.1:Y.3) %>%
gather(key2, value = M, M.1:M.3) %>%
head()
#> # A tibble: 6 x 5
#> X key Y key2 M
#> <chr> <chr> <chr> <chr> <int>
#> 1 K3 Y.1 L M.1 21
#> 2 K8 Y.1 N M.1 31
#> 3 K2 Y.1 L M.1 8
#> 4 K3 Y.2 N M.1 21
#> 5 K8 Y.2 <NA> M.1 31
#> 6 K2 Y.2 Q M.1 8
)创建一列,然后将数字值相加。我将K2,K3
放在了分组中,这样汇总后就不会被丢弃。
x.all
然后将其恢复为宽的形状,其中包含用于不同df %>%
gather(key, value = Y, Y.1:Y.3) %>%
gather(key2, value = M, M.1:M.3) %>%
group_by(Y) %>%
mutate(x.all = sort(X) %>% unique() %>% paste(collapse = ",")) %>%
group_by(Y, key2, x.all) %>%
summarise(sum = sum(M, na.rm = T)) %>%
head()
#> # A tibble: 6 x 4
#> # Groups: Y, key2 [6]
#> Y key2 x.all sum
#> <chr> <chr> <chr> <int>
#> 1 L M.1 K2,K3 29
#> 2 L M.2 K2,K3 6
#> 3 L M.3 K2,K3 13
#> 4 N M.1 K3,K8 52
#> 5 N M.2 K3,K8 7
#> 6 N M.3 K3,K8 40
变量的列:
M
由reprex package(v0.2.1)于2018-10-17创建
答案 1 :(得分:0)
1)dplyr
这里是一种dplyr
的方法,但从reshape
开始(它具有强大的功能,但是其参数的工作方式却难以记住)。
library(dplyr)
(df2 <- reshape(df1, varying = c("Y.1", "Y.2", "Y.3"), direction = "long") %>%
group_by(Y))
# A tibble: 9 x 7
# Groups: Y [6]
# X M.1 M.2 M.3 time Y id
#* <chr> <int> <int> <int> <dbl> <chr> <int>
#1 K3 21 6 11 1 L 1
#2 K8 31 1 29 1 N 2
#3 K2 8 0 2 1 L 3
#4 K3 21 6 11 2 N 1
#5 K8 31 1 29 2 NA 2
#6 K2 8 0 2 2 Q 3
#7 K3 21 6 11 3 X 1
#8 K8 31 1 29 3 NA 2
#9 K2 8 0 2 3 Z 3
现在,在分别总结left_join
和X
之后,我们可以使用c("M.1", "M.2", "M.3")
。
left_join(
summarise_at(df2, c("M.1", "M.2", "M.3"), .funs = sum),
mmarise(df2, X = toString(unique(X)))
)
# A tibble: 6 x 5
# Y M.1 M.2 M.3 X
# <chr> <int> <int> <int> <chr>
#1 L 29 6 13 K3, K2
#2 N 52 7 40 K8, K3
#3 Q 8 0 2 K2
#4 X 21 6 11 K3
#5 Z 8 0 2 K2
#6 NA 62 2 58 K8
2)基本R
从df2
开始,这与base R
中的想法相同,但请注意NA
迷路了。
df2 <- reshape(df1, varying = c("Y.1", "Y.2", "Y.3"), direction = "long")
merge(
aggregate(cbind(M.1, M.2, M.3) ~ Y, df2, sum),
aggregate(X ~ Y, df2, toString)
)
# Y M.1 M.2 M.3 X
#1 L 29 6 13 K3, K2
#2 N 52 7 40 K8, K3
#3 Q 8 0 2 K2
#4 X 21 6 11 K3
#5 Z 8 0 2 K2
3)data.table
library(data.table)
setDT(df1)
df2 <- melt(df1, measure.vars = patterns("Y."), value.name = "Y")
# I'm sure there must be a cleverer way than this
df2[df2[, .(X = toString(unique(X))), by = Y], lapply(.SD, sum), .SDcols = c("M.1", "M.2", "M.3"), by = Y, on = "Y"]
数据
df1 <- structure(list(X = c("K3", "K8", "K2"), M.1 = c(21L, 31L, 8L),
M.2 = c(6L, 1L, 0L), M.3 = c(11L, 29L, 2L), Y.1 = c("L",
"N", "L"), Y.2 = c("N", NA, "Q"), Y.3 = c("X", NA, "Z")), .Names = c("X",
"M.1", "M.2", "M.3", "Y.1", "Y.2", "Y.3"), class = "data.frame", row.names = c(NA,
-3L))