首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >R:在dataframe中根据连续条目(两者之间的不等间距)更改条目的值

R:在dataframe中根据连续条目(两者之间的不等间距)更改条目的值
EN

Stack Overflow用户
提问于 2017-12-14 23:01:38
回答 2查看 57关注 0票数 0

我需要在我的大脑成像数据中编辑一些ER标记,这基本上意味着,如果连续的非零条目具有一定的值,我需要更改条目的值。我不知道我是否需要为它编写一个自定义函数(如果我需要这样做的话,请在正确的方向上推动一下)。

在一个示例中更好地说明我的问题(假设col标记是包含有关标记值的信息的16000行数据集的片段):

代码语言:javascript
复制
markers = matrix(c(1,0,0,0,0,2,0,0,0,0,1,0,0,0,3), ncol = 1)

我需要将值1改为(f.e.)如果下一个非零项为2(但如果为3),则为9。它们之间没有相等的间距(这意味着,这两个感兴趣的条目之间可能有3-8个零项。

我很乐意提供任何帮助,因为我真的不想手动更改这些值。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-12-14 23:24:53

也许不是最简单的方法,但是这里有一种使用基本R::我将一步一步地编写它的方法,这样您就可以看到在每一步中发生了什么。

先做rle

代码语言:javascript
复制
b <- rle(markers[,1])$values

检查哪些元素是1

代码语言:javascript
复制
z <- which(b==1)

现在检查0是否是前面的一个元素,如果是,取前面两个元素的索引

代码语言:javascript
复制
k <- ifelse(b[z + 1] == 0, z + 2, z + 1)

现在检查这些元素是否等于2,删除任何不是的元素。

代码语言:javascript
复制
v <- ifelse(b[k] == 2, z, NA)
v <- na.omit(v)

将剩下的索引值更改为9。

代码语言:javascript
复制
b[v] = 9 

把向量拿回来

代码语言:javascript
复制
rep(b, times = rle(markers[,1])$lengths)
#output
[1] 9 0 0 0 0 2 0 0 0 0 1 0 0 0 3

markers[,1]
#output
[1] 1 0 0 0 0 2 0 0 0 0 1 0 0 0 3

以下是一个小小的基准:

代码语言:javascript
复制
evers <- function(markers){require(dplyr);
  df <- sapply(1:nrow(markers), function(i) lead(markers, i - 1))
  idx <- which(df[, 1] == 1);
  idx
  idx <- idx[sapply(idx, function(i) any(df[i, 2:nrow(df)] == 2, na.rm = TRUE))]}

mss <- function(markers) {
  b <- rle(markers[,1])$values
  z <- which(b==1)
  k <- ifelse(b[z + 1] == 0, z + 2, z + 1)
  v <- ifelse(b[k] == 2, z, NA)
  v <- na.omit(v)
  b[v] = 9 

  rep(b, times = rle(markers[,1])$lengths)
  b
}

microbenchmark(
mss(markers),
evers(markers)
)
#Unit: microseconds
           expr     min      lq     mean  median       uq       max neval
   mss(markers)  42.667  45.555 118.2324  50.046  52.1315  6681.986   100
 evans(markers) 128.322 133.775 271.2453 136.021 140.6725 12645.376   100

拥有更大的数据集:

代码语言:javascript
复制
markers = matrix(rep(c(1,0,0,0,0,2,0,0,0,0,1,0,0,0,3), times = 1000), ncol = 1)
#output
Unit: microseconds
           expr       min           lq        mean       median          uq         max neval
   mss(markers)     823.5     904.5025    1144.658     957.5945    1045.174     5455.24   100
 evans(markers) 2940719.3 3185982.7470 3453372.766 3242533.4130 3299607.308 11652090.81   100
票数 0
EN

Stack Overflow用户

发布于 2017-12-14 23:39:11

另一种方法是:

代码语言:javascript
复制
markers <- matrix(c(1,0,0,0,0,2,0,0,0,0,1,0,0,0,3), ncol = 1)

创建一个包含所有可能滞后的dataframe版本的markers

代码语言:javascript
复制
# Create dataframe of lagged vectors
require(dplyr);
df <- sapply(1:nrow(markers), function(i) lead(markers, i - 1));

获取非滞后向量中的条目等于1的行索引。

代码语言:javascript
复制
# Select rows where entry = 1
idx <- which(df[, 1] == 1);
idx;
#[1]  1 11

只保留那些对于行idxany中存在一个条目等于2的索引( markers的滞后版本)。

代码语言:javascript
复制
# Keep only those rows where entry = 1 followed by a lagged 2
idx <- idx[sapply(idx, function(i) any(df[i, 2:nrow(df)] == 2, na.rm = TRUE))];

最后,将这些行的值设置为9。

代码语言:javascript
复制
# Set those entries equal to 9
markers[idx, 1] <- 9;

markers;
#      [,1]
# [1,]    9
# [2,]    0
# [3,]    0
# [4,]    0
# [5,]    0
# [6,]    2
# [7,]    0
# [8,]    0
# [9,]    0
#[10,]    0
#[11,]    1
#[12,]    0
#[13,]    0
#[14,]    0
#[15,]    3

更新

在第二个markers示例中:

代码语言:javascript
复制
markers <- matrix(c(1,0,0,0,0,2,0,0,0,0,1,0,0,0,2,0,0,0,0,1,0,0,0,0,3), ncol = 1);
df <- sapply(1:nrow(markers), function(i) lead(markers, i - 1));
idx <- which(df[, 1] == 1);
idx <- idx[sapply(idx, function(i) any(df[i, 2:nrow(df)] == 2, na.rm = TRUE))];
markers[idx, 1] <- 9;
markers;
#      [,1]
# [1,]    9
# [2,]    0
# [3,]    0
# [4,]    0
# [5,]    0
# [6,]    2
# [7,]    0
# [8,]    0
# [9,]    0
#[10,]    0
#[11,]    9
#[12,]    0
#[13,]    0
#[14,]    0
#[15,]    2
#[16,]    0
#[17,]    0
#[18,]    0
#[19,]    0
#[20,]    1
#[21,]    0
#[22,]    0
#[23,]    0
#[24,]    0
#[25,]    3
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/47823452

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档