这个问题听起来在这里得到了部分回答,但这对我来说还不够具体.当通过引用更新对象以及复制对象时,我想更好地理解.
更简单的例子是矢量增长.下面的代码在R中非常低效,因为在循环之前没有分配内存,并且在每次迭代时都进行了复制.
x = runif(10)
y = c()
for(i in 2:length(x))
y = c(y, x[i] - x[i-1])
Run Code Online (Sandbox Code Playgroud)
分配内存使能保留一些内存,而无需在每次迭代时重新分配内存.因此,这个代码速度极快,特别是对于长向量.
x = runif(10)
y = numeric(length(x))
for(i in 2:length(x))
y[i] = x[i] - x[i-1]
Run Code Online (Sandbox Code Playgroud)
这是我的问题.实际上,当矢量更新时,它确实会移动.有一个副本,如下所示.
a = 1:10
pryr::tracemem(a)
[1] "<0xf34a268>"
a[1] <- 0L
tracemem[0xf34a268 -> 0x4ab0c3f8]:
a[3] <-0L
tracemem[0x4ab0c3f8 -> 0xf2b0a48]:
Run Code Online (Sandbox Code Playgroud)
但在循环中,此副本不会发生
y = numeric(length(x))
for(i in 2:length(x))
{
y[i] = x[i] - x[i-1]
print(address(y))
}
Run Code Online (Sandbox Code Playgroud)
给
[1] "0xe849dc0"
[1] "0xe849dc0"
[1] "0xe849dc0"
[1] "0xe849dc0" …Run Code Online (Sandbox Code Playgroud) 在更改日志中,data.table v1.12.0我注意到以下内容:
子集,排序和分组现在使用更多并行性
我测试过我是否可以加快一些分组但没有任何成功.我做了几个不同的测试,我总是得到相同的结果.分组实际上是并行的吗?也许我没有正确使用线程选项?正如您所看到的那样data.table已经编译,openmp否则会setDTthread打印一条消息告诉用户没有支持openmp.这是我的一个测试的再现示例.
library(data.table)
n = 5e6
k = 1e4
DT = data.table(x = runif(n), y = runif(n), grp = sample(1:k, n, TRUE))
# Any function not too fast
f = function(x,y) as.list(eigen(cov(cbind(x,y)), only.values = TRUE)$value)
setDTthreads(1)
getDTthreads()
#> [1] 1
system.time(DT[ , f(x,y), by = grp])
#> utilisateur système écoulé
#> 3.365 0.008 3.374
setDTthreads(0)
getDTthreads(T)
#> omp_get_max_threads() = 4
#> omp_get_thread_limit() = 2147483647
#> DTthreads = 0 …Run Code Online (Sandbox Code Playgroud) 这个问题在这里有部分答案,但问题太具体了,我无法将其应用于我自己的问题.
我想在使用时跳过NA组的潜在重量计算by.
library(data.table)
DT = data.table(X = sample(10),
Y = sample(10),
g1 = sample(letters[1:2], 10, TRUE),
g2 = sample(letters[1:2], 10, TRUE))
set(DT, 1L, 3L, NA)
set(DT, 1L, 4L, NA)
set(DT, 6L, 3L, NA)
set(DT, 6L, 4L, NA)
DT[, mean(X*Y), by = .(g1,g2)]
Run Code Online (Sandbox Code Playgroud)
在这里,我们可以看到最多有5个组,包括该(NA, NA)组.考虑到(i)该组是无用的(ii)这些组可能非常大并且(iii)实际计算比mean(X*Y)我能以有效方式跳过该组更复杂?我的意思是,没有创建剩余表的副本.确实以下工作.
DT2 = data.table:::na.omit.data.table(DT, cols = c("g1", "g2"))
DT2[, mean(X*Y), by = .(g1,g2)]
Run Code Online (Sandbox Code Playgroud) 海湾合作委员会8增加了-Wstringop-truncation警告.来自https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82944:
在GCC 8.0中通过r254630为bug 81117添加的-Wstringop-truncation警告专门用于突出显示strncpy函数的非预期用途,该函数截断源字符串中的终止NUL字符.请求中给出的此类滥用的示例如下:
char buf[2];
void test (const char* str)
{
strncpy (buf, str, strlen (str));
}
Run Code Online (Sandbox Code Playgroud)
我用这段代码得到了同样的警告.
strncpy(this->name, name, 32);
warning: 'char* strncpy(char*, const char*, size_t)' specified bound 32 equals destination size [-Wstringop-truncation`]
Run Code Online (Sandbox Code Playgroud)
考虑到this->name是char name[32]和name是一个char*具有长度可能比32更大我想复制name成this->name和截断它,如果它是大于32更大的应该size_t是31而不是32?我糊涂了.this->nameNUL终止并不是强制性的.
在不久的将来,我的包中将需要 64 位整数。我正在研究基于该bit64包的可行性。data.table基本上,我计划在 S3类中包含一列或多列interger64,并计划使用 Rcpp 将此表传递给 C++ 函数。
以下来自Rcpp 图库的nanotime 示例清楚地解释了如何在 double 向量上构建 64 位 int 向量,并解释如何创建integer64从 C++ 到 R 的对象。
我现在想知道如何处理interger64从 R 到 C++ 的问题。我想我可以颠倒这个原则。
void useInt64(NumericVector v)
{
double len = v.size();
std::vector<int64_t> n(len);
// transfers values 'keeping bits' but changing type
// using reinterpret_cast would get us a warning
std::memcpy(&(n[0]), &(v[0]), len * sizeof(double));
// use n in further computations
}
Run Code Online (Sandbox Code Playgroud)
那是对的吗?还有其他方法可以做到这一点吗?我们可以使用包装器吗as<std::vector<int64_t>>(v)?对于最后一个问题,我猜转换不是基于位到位的复制。
我的包.so文件大于 3 MB(最多 10 MB),具体取决于编译器和系统。这会R CMD check在我的包中生成一个注释多年。我的包不包含这么多代码,所以我最终搜索以减小大小,我发现了 Dirk Eddelbuettel 的这篇优秀文章。
按照我SHLIB_CXX11LDFLAGS = -Wl,-S -shared在我的.R/Makevars库中添加的建议,我的库大小从 10.4 MB 下降到 580 KB!我第一次有 0 个错误、0 个警告和 0 个注释。是的!
然而,这只是局部解决方案。在帖子的最后,建议以下内容src/Makevars
strippedLib: $(SHLIB)
if test -e "/usr/bin/strip"; then /usr/bin/strip --strip-debug $(SHLIB); fi
.phony: strippedLib
Run Code Online (Sandbox Code Playgroud)
但有人提到:
而且这个方案甚至可能通过 CRAN 审核,但我还没有尝试过。
我的问题如下:
我在SO主题中读到了Matt Dowle的答案,该答案涉及在shallow中创建浅表副本的功能data.table。但是,我再也找不到该主题。
data.table没有名为的任何导出函数shallow。有一个内部文件,但没有记录。我可以安全使用吗?它的行为是什么?
我想做的是一个大表的内存有效副本。让我们DT做一个有n列的大表,并使用f一个函数有效地增加一个列。这样有可能吗?
DT2 = f(DT)
Run Code Online (Sandbox Code Playgroud)
与DT2是,其中data.table包含n指向原始地址的列(无较深的副本),并且仅存在一个用于的地址DT2。如果是,我可以追加DT1什么DT2[, col3 := NULL]?
在他的书中,Hadley Wickam 解释了为什么空向量在memory部分中是 40 个字节。但是矩阵呢?矩阵的属性中也至少有两个整数来存储列数和行数。但这不足以解释为什么空矩阵是 208 字节。我期待像 48 字节这样的东西。
> object.size(matrix())
208 bytes
Run Code Online (Sandbox Code Playgroud) 我今天将 R 3.4.4 更新为 R 3.5.0。我的包裹不能再通过R CMD check了。它在 处失败checking whether package can be installed ... ERROR。
另一方面,我的包可以工作,只要我不检查它,我就可以安装和使用它。
错误如下:
Error: package or namespace load failed for ‘sp’:
package ‘lattice’ was installed by an R version with different internals; it needs to be reinstalled for use with this R version
Error : package ‘sp’ could not be loaded
Run Code Online (Sandbox Code Playgroud)
我尝试通过lattice以下方式重新安装:
sudo apt-get --reinstall install r-cran-lattice
Run Code Online (Sandbox Code Playgroud)
或者
remove.packages("lattice", lib="~/R/x86_64-pc-linux-gnu-library/3.5")
install.package("lattice")
Run Code Online (Sandbox Code Playgroud)
lattice在这两种情况下都正确安装了软件包。但这并不能解决我的问题。此外,我确保有一个lattice删除一个版本r-cran或自编译版本的单一版本。什么都行不通。
编辑顺便说一句,我可以做到 …
我试图安装R与USBAN从devel的ASAN摇杆。按照自述文件我试过:
sudo docker run --rm -ti rocker/r-devel-san
Run Code Online (Sandbox Code Playgroud)
这花了很长时间下载,但最后没问题。然后我安装了sanitizers包来测试 R 是否存在已知错误。
install.package("sanitizers")
Run Code Online (Sandbox Code Playgroud)
我试图得到一个错误
> sanitizers::stackAddressSanitize(42)
[1] 24
> sanitizers::heapAddressSanitize(1)
[1] 0
Run Code Online (Sandbox Code Playgroud)
我没有收到任何错误,所以我猜我用 docker 运行的 R 版本不是用消毒剂支持构建的。或者我只是在某个地方错过了一些东西。这是我第一次使用 docker。
激光雷达数据只是 3D 坐标,通常采用las文件格式。\xd0\xa1内容示例
library(rgdal)\nlibrary(raster)\nlibrary(tmap)\nlibrary(tmaptools)\nlibrary(lidR)\nlibrary(RStoolbox)\nlas_cat <- readLAScatalog("C:/1/078-638.las")\nsummary(las_cat)\nopt_chunk_size(las_cat) <- 500\nplot(las_cat, chunk_pattern = TRUE)\nlas_cat\n#> class : LAScatalog (v1.2 format 1)\n#> extent : 637999, 638240.5, 6077999, 6079999 (xmin, xmax, ymin, ymax)\n#> coord. ref. : NA \n#> area : 483081.1 units\xc2\xb2\n#> points : 3.68 million points\n#> density : 7.6 points/units\xc2\xb2\n#> density : 5.6 pulses/units\xc2\xb2\n#> num. files : 1\nRun Code Online (Sandbox Code Playgroud)\n有没有办法获得data.frameR 的典型点坐标?\n作为示例,我们可以使用来自此http://data.wvgis.wvu.edu/elevation/的数据。\n此外,有没有办法获得角度反射,data.frame激光雷达文件中的反射数量?
遵循这两个资源:
我写了一个Delaunay三角剖分boost.如果点坐标是积分的,它可以正常工作(我生成了几个随机测试,但没有观察到错误).但是,如果这些点是非整数的,我会发现许多不正确的三角剖分,边缘缺失或边缘错误.
例如,此图像已使用舍入值构建并且是正确的(请参阅下面的代码)
但是这个图像是用原始值构建的并且不正确(参见下面的代码)
此代码重现了这两个示例(没有显示).
#include <boost/polygon/voronoi.hpp>
using boost::polygon::voronoi_builder;
using boost::polygon::voronoi_diagram;
struct Point
{
double a;
double b;
Point(double x, double y) : a(x), b(y) {}
};
namespace boost
{
namespace polygon
{
template <>
struct geometry_concept<Point>
{
typedef point_concept type;
};
template <>
struct point_traits<Point>
{
typedef double coordinate_type;
static inline coordinate_type get(const Point& point, orientation_2d orient)
{
return (orient == HORIZONTAL) ? point.a : point.b;
}
};
} // polygon
} // boost
int …Run Code Online (Sandbox Code Playgroud) 我想构建一个向量的向量.这个问题已经多次发布在SO上,但我找不到令人满意的答案.那是因为:
基本上我希望以后可以在伪代码中做类似的事情
types = ["char", "int", "double", "int"]
container<vector> x
foreach (type in types)
{
if (type == "char")
x.push_back(vector<char>)
else if (type == "int")
x.push_back(vector<int>)
else
x.push_back(vector<double>)
}
Run Code Online (Sandbox Code Playgroud)
然后我希望能够做到这一点
x[0].push_back("a")
x[1].push_back(1)
x[2].push_back(3.1416)
Run Code Online (Sandbox Code Playgroud)
我想boost::any可能会对我有所帮助,但我还不熟悉.
关键是,即使听起来很奇怪,这也是我想做的事情.我不想要一个结构向量,我真的想要一个包含std::vector不同类型的容器(无论哪一个).原因是因为我正在阅读二进制文件.文件的标题表示数据的数量及其类型,但它可以从文件更改为另一个文件.因此在编译时无法知道.