使用mutate的自定义函数不起作用

时间:2017-04-07 12:54:27

标签: r dplyr

某些自定义函数在mutate中不起作用。你能解释一下吗? 为什么calc2和calc3不起作用,以及如何解决它们才能正常工作?

    library(dplyr)
    m <- matrix(c(1,2,3,4,5,6,7,8,9), nrow = 3, byrow = T)        

    calc <- function(x1,x2,x3){ #scalar
      return(x1 + x2 + x3)
    }

    calc2 <- function(x){ #vector
      return(x[1] + x[2] + x[3])
    }

    calc3 <- function(x){ #list
      x <- unlist(x)
      return(sum(x))
    }

    as.data.frame(m) %>% 
      mutate(val  = calc(V1,V2,V3), #OK
             val2 = calc2(c(V1,V2,V3) ), #NG
             val3 = calc3(list(V1,V2,V3))) #NG

以下是输出:

    V1 V2 V3 val val2 val3
    1  2  3   6   12   45
    4  5  6  15   12   45
    7  8  9  24   12   45

2 个答案:

答案 0 :(得分:5)

这与dplyr / **Controller for loop** function loop_item() { --Showing the Category -- $category = $this->db->query(" SELECT DISTINCT b.id_category,b.category_name name,a.id from tbl_a a LEFT JOIN tbl_b b on a.id_category = b.id_category where a.id_category !=''")->result_array(); -- End Showing the Category -- -- Loop for item inside category -- foreach($category as $key => $value) { $category[$key]['items'] = $this->db->query(" SELECT a.id,a.marca marca,a.detalle detalle,a.precio precio FROM tbl_a a LEFT JOIN tbl_b b on a.id_category=b.id_category where a.id_category=".$value['id_category'])->result_array(); } -- End Loop for item inside category -- $d['listcategory'] = $category; } **Views** <?php $i=1;foreach($listcategory as $value) { echo $value['nama']."<br>"; ?> <table> <thead> <th>Codigo</th> <th>Marca</th> <th>Detalle</th> <th>Precio</th> </thead> <tbody> <?php $number= 1; foreach($value['items'] as $val){ ?> <tr> <td><?= $number;?></td> <td><?= $val['marca'];?></td> <td><?= $val['detalle'];?></td> <td><?= $val['precio'];?></td> </tr> <?php $number++; } ?> </tbody> 无关。你根本就没有正确的矢量化。让我们检查mutatecalc2得到什么作为输入,是吗?

calc3 calc2。也就是说,所有元素都连接成一个向量。然后你添加前三个:1 + 4 + 7 = 12.

x = c(1L, 4L, 7L, 2L, 5L, 8L, 3L, 6L, 9L) 中,calc3更有意义,除了您x之外;之后,unlist与上述相同,然后x所有元素:sum = 45。

sum(x)基本上无法挽救,但您可以通过矢量化修复calc2

calc3

最后,您可以使用calc3 = function (x) { Reduce(`+`, x) } 参数充分利用calccalc3

...

用法:

calc = function (...) {
    Reduce(`+`, list(...))
}

答案 1 :(得分:2)

我们可以在不使用pos1<-c(5,15,25,40,80,5,18,22,38,84,5,16,50,92,31,50,20,30,50,70,27,50,60,50,90,20,40) pos2<-c(10,17,30,42,90,10,20,24,42,87,10,19,52,100,40,70,25,32,60,90,30,60,71,60,100,25,50) chr<-c(1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2) n<-c(25,65,78,56,35,78,58,98,14,25,65,85,98,74,20,36,48,98,52,69,21,47,53,10,12,37,82) pop<-c("A","A","A","A","A","B","B","B","B","C","C","C","C","C","D","D","A","A","A","A","B","B","B","C","C","D","D") data<-data.frame(pos1,pos2,chr,pop,n,stringsAsFactors = FALSE) library(intervals) data<-data[data$pop!="D",] #remove irrelevant D entries rownames(data) <- seq_len(nrow(data)) #reset rownames to allow for removed Ds #set ints as a list of intervals (as required by intervals package) ints <- tapply(1:nrow(data),data$pop,function(v) Intervals(as.matrix(data[v,c("pos1","pos2")]), closed=c(FALSE,FALSE), #this is where you adjust open/closed lower and upper ends of the intervals - TRUE means end value included type="Z")) #Z is integers pops <- unique(data$pop) #unique values of pop popidx <- lapply(pops,function(x) which(data$pop==x)) #list of indices of these values in data names(popidx) <- pops #sets is a df of all pairwise combinations to check sets <- expand.grid(pops,pops,stringsAsFactors = FALSE) sets <- sets[sets$Var1!=sets$Var2,] olap <- lapply(1:nrow(sets),function(i) interval_overlap(ints[[sets$Var1[i]]],ints[[sets$Var2[i]]])) #list of overlaps olap <- lapply(1:nrow(sets),function(i) { df<-as.data.frame(olap[[i]],stringsAsFactors=FALSE) df$pos1 <- as.numeric(rownames(df)) df$pos2 <- sapply(1:nrow(df),function(j) popidx[[sets$Var2[i]]][df[j,1][[1]][1]]) return(df)}) #tidy up as dfs, with correct indices in data (rather than in ints) olap <- do.call(rbind,olap)[,-1] #join dataframes olap$olaps <- !is.na(olap$pos2) #identify those with overlaps #group by unique pos1 and identify max and min no of overlaps with other groups olap <- data.frame(minoverlap=tapply(olap$olaps,olap$pos1,min),maxoverlap=tapply(olap$olaps,olap$pos1,max)) olap$rowno <- as.numeric(rownames(olap)) uniques <- data[olap$rowno[olap$maxoverlap==0],] #intervals appearing in just one pop commons <- data[olap$rowno[olap$minoverlap>0],] #intervals with an overlap in all other pops

更改OP功能的情况下执行此操作
library(ggplot2)
library(sf)
library(rnaturalearth)
library(dplyr)

crs <- "+proj=laea +lat_0=52 +lon_0=10 +x_0=4321000 +y_0=3210000 +datum=WGS84 +units=m +no_defs"

ctrys50m <- ne_countries(scale = 50, type = "countries", returnclass = "sf") %>%
  select(iso_a3, iso_n3, admin)

sphere <- st_graticule(ndiscr = 10000, margin = 10e-6) %>%
  st_transform(crs = crs) %>%
  st_convex_hull() %>%
  summarise(geometry = st_union(geometry))

ggplot()  +
  geom_sf(data = sphere, fill = "#D8F4FF", alpha = 0.7) +
  geom_sf(data = ctrys50m, fill="grey") +
  theme_bw()