根据字符串匹配选择数据帧的行,然后求和并转换这些行

时间:2016-09-23 13:47:03

标签: r transform lapply

我有一个包含18个数据框的列表,每个数据框都有不同的行数和随机空白行,结构如下:

    l = c("D1", "D1", "D1", "", "D1", "D1", "D1", "D2", "D2", "D2", "D2", "", "D3", "D3", "D3", "D3")
    a = c("Al", "Al", "St", "", "St", "Un", "St", "Al", "Al", "St", "St", "", "Al", "Al", "St", "St")
    b = c(6000, 4980, 123, "", 98, 87, 51, 10989, 8756, 457, 233, "", 989, 743, 67, 55)
    mydf = data.frame("Location" = l, "Name" = a, "count" = b)
    mydf
        Location Name count
1        D1   Al  6000
2        D1   Al  4980
3        D1   St   123
4                     
5        D1   St    98
6        D1   Un    87
7        D1   St    51
8        D2   Al 10989
9        D2   Al  8756
10       D2   St   457
11       D2   St   233
12                    
13       D3   Al   989
14       D3   Al   743
15       D3   St    67
16       D3   St    55

我的数据包含18个数据框:

sapply(mydata, dim)
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12] [,13] [,14] [,15] [,16] [,17] [,18]
[1,]  171  146  132  147  149  148  138  143  114   111   115   101   112   218   122    96   156   128
[2,]   10   10   10   10   10   10   10   10   10    10    10    10    10    10    10    10    10    10 

我想使用transform向我的数据框添加一列,其中包含每个位置的Al计数总和。我打算用相同的值填充整个新列。我以为我可以找到那些包含字符串" Al"然后应用sum函数但这不起作用。这是我试图使用的代码:

add.al.sum = function(df){
    als = df[grep("Al", df$Name),]
    alsum = sum(als, na.rm = TRUE)
    transform(df, Al.sum = c(alsum))
}
mydf = lapply(mydf, function(x) add.al.sum(x))

这不能做我想做的事。我希望我的转换数据表看起来像这样; 不需要保留空行

Location Name count  Al.sum
1        D1   Al  6000     10980
2        D1   Al  4980     10980
3        D1   St   123     10980
4                          NA
5        D1   St    98     10980
6        D1   Un    87     10980
7        D1   St    51     10980
8        D2   Al 10989     19745
9        D2   Al  8756     19745
10       D2   St   457     19745
11       D2   St   233     19745 
12                         NA
13       D3   Al   989     1732
14       D3   Al   743     1732
15       D3   St    67     1732
16       D3   St    55     1732

它实际上告诉我Error in df$Name : $ operator is invalid for atomic vectors。我的实际数据与示例数据之间的唯一区别是,我的实际数据中的count列列为int而不是num。我需要这个来处理int列中的count值。

在我得到Al计数的总和之后,我将重复这个过程,以便在各自的列中得到St和Un计数的总和。

编辑:我扩展了示例数据,并添加了有关我正在使用的数据框列表的更多信息。

2 个答案:

答案 0 :(得分:2)

我们可以使用dplyr

library(dplyr)
mydf %>% 
   group_by(Location) %>%
   mutate(Al.sum = sum(count[Name == 'Al']))

#Source: local data frame [10 x 4]
#Groups: Location [2]

#   Location   Name count Al.sum
#     <fctr> <fctr> <dbl>  <dbl>
#1        D1     Al  6000  10980
#2        D1     Al  4980  10980
#3        D1     St   123  10980
#4        D1     St    98  10980
#5        D1     Un    87  10980
#6        D1     St    51  10980
#7        D2     Al 10989  19745
#8        D2     Al  8756  19745
#9        D2     St   457  19745
#10       D2     St   233  19745

或通过data.table

library(data.table)
setDT(mydf)[, Al.sum := sum(count[Name == 'Al']), by = Location]

答案 1 :(得分:1)

这不使用任何包,只有一行代码。对于那些(Name == 'Al') * count等于count的行,Name等于'A1',对于那些不为ifelse(Name == 'A1', count, 0)的行,等于0。 (或者我们可以用ave替换该表达式。然后,我们使用Location将它们加起来mydf0。请注意,我们使用的是底部注释2中定义的transform(mydf0, Al.sum = ave((Name == 'Al') * count, Location, FUN = sum))

   Location Name count Al.sum
1        D1   Al  6000  10980
2        D1   Al  4980  10980
3        D1   St   123  10980
4        D1   St    98  10980
5        D1   Un    87  10980
6        D1   St    51  10980
7        D2   Al 10989  19745
8        D2   Al  8756  19745
9        D2   St   457  19745
10       D2   St   233  19745

,并提供:

sum(..., na.rm = TRUE)

示例数据没有NA值,因此我们没有使用sum,但是如果要将其扩展到要删除NA值的其他数据,则将function(x) sum(x, na.rm = TRUE)替换为L

<强>列表

这个问题提到了多个数据框,但没有给出一个例子;所以我们假设我们有下面显示的数据框列表L <- list(mydf0, mydf0) lapply(L, transform, Al.sum = ave((Name == 'Al') * count, Location, FUN = sum)) 。然后:

grepl

注意:我们可以在这样的问题中修复解决方案。 by导致逻辑向量在乘法时被视为0/1向量,因此非Al计数归零。然后Locationrbind应用于Locationadd.al.sum = function(df) { transform(df, Al.sum = sum(grepl("Al", Name) * count, na.rm = TRUE)) } do.call("rbind", by(mydf0, mydf$Location, add.al.sum)) 将各个部分(每个mydf0 <- mydf # preserve mydf just in case mydf0[] <- lapply(mydf0, as.character) # make all cols character mydf0 <- transform(mydf0, count = as.numeric(count)) # make count numeric mydf0 <- subset(mydf0, Location != "") # remove blank lines 一个)放在一起。

git-svn

注2:首先修复数据框:

git-svn

更简单的方法是确保在读取数据时忽略空行并使列成为字符,但这取决于它们的读取方式。