R-与多个列中的几行匹配的模式/字符的和值

时间:2018-10-17 21:45:13

标签: r dataframe sum aggregate multiple-columns

我希望对“ 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)

非常感谢您的帮助!

2 个答案:

答案 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 gatherY 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_joinX之后,我们可以使用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))