如何在数据帧的每一列中有效地划分前任的后继者

时间:2015-09-02 20:01:29

标签: r performance dataframe cbind

我创建了dataframe myDF,如下所示:

a <- 1:4
b <- seq(3, 16, length=4)
myDF <- data.frame(a=a, b=b)

看起来像这样:

  a         b
1 1  3.000000
2 2  7.333333
3 3 11.666667
4 4 16.000000

现在我想在每列中分割后续的前导和后继,将结果添加到现有的数据帧,用NA替换每列中缺少的一个值并添加新的列名。对于上面的示例,我期望的结果如下所示:

  a         b     amod     bmod
1 1  3.000000       NA       NA
2 2  7.333333 2.000000 2.444444
3 3 11.666667 1.500000 1.590909
4 4 16.000000 1.333333 1.371429

因此,在列a中,2除以1,将3除以2,将4除以3,结果存储在amod中。

我现在这样做的方式是这样的:

divStuff <-function(aCol){

  newCol <- aCol[2:length(aCol)]/aCol[1:length(aCol) - 1]
  newCol <- c(NA, newCol)

  return(newCol)
}
newDF <- data.frame(lapply(myDF, divStuff))
names(newDF) <- paste(names(myDF), "mod", sep="")
endDF <- cbind(myDF, newDF)

我编写了一个函数divStuff,它执行除法,然后调用lapply,它将此函数应用于数据框的每一列。

现在我想知道这是否是这样做的方式,或者是否有更聪明的方法来进行这样的操作,例如通过自动添加cbind来避免cbind来电或以newCol <- c(NA, newCol)方式避开行NA。我没有找到一个好方法,所有解决方案看起来都与this one类似。

2 个答案:

答案 0 :(得分:7)

这是一个快速// $templateFile = original, unedited template; $newFile = new file name to be created; $row = array of data to merge in function mailmerge($templateFile, $newFile, $row) { if (!copy($templateFile, $newFile)) // make a duplicate so we dont overwrite the template return false; // could not duplicate template $xmldata = get_docx_xml($newFile); $zip = new ZipArchive(); if ($zip->open($newFile, ZIPARCHIVE::CHECKCONS) !== TRUE) return false; // probably not a docx file $file = 'word/document.xml'; $data = $zip->getFromName($file); foreach ($row as $key => $value) { $data = str_replace($key, xml_escape($value), $data); } $zip->deleteName($file); $zip->addFromString($file, $data); $zip->close(); return true; } 版本(使用devel version on GH

data.table

或类似于library(data.table) ## V 1.9.5 setDT(myDF)[, paste0(names(myDF), "mod") := lapply(.SD, function(x) x/shift(x))] # a b amod bmod # 1: 1 3.000000 NA NA # 2: 2 7.333333 2.000000 2.444444 # 3: 3 11.666667 1.500000 1.590909 # 4: 4 16.000000 1.333333 1.371429 ,但您可能想要使用列名称(这是因为dplyr中的错误(?),当它删除原始列并且不重命名时给定单个函数时得到的结果)

mutate_each

答案 1 :(得分:6)

使用base R

myDF[,paste0(names(myDF), "mod")] <- sapply(myDF, function(x) c(NA, x[-1]/head(x,-1)))
#  a         b     amod     bmod
#1 1  3.000000       NA       NA
#2 2  7.333333 2.000000 2.444444
#3 3 11.666667 1.500000 1.590909
#4 4 16.000000 1.333333 1.371429