当前位置: 首页 > 知识库问答 >
问题:

为每个连续序列创建组号

谷彦君
2023-03-14

我有数据。下面的框架。我想添加一列“g”,它根据列h\u no中的连续序列对数据进行分类。也就是说,如最后一列“g”所示,h_no1、2、3、4的第一个序列是组1,h_no(1到7)的第二个序列是组2,依此类推。

h_no   h_freq    h_freqsq g
1     0.09091 0.008264628 1
2     0.00000 0.000000000 1
3     0.04545 0.002065702 1
4     0.00000 0.000000000 1  
1     0.13636 0.018594050 2
2     0.00000 0.000000000 2
3     0.00000 0.000000000 2
4     0.04545 0.002065702 2
5     0.31818 0.101238512 2
6     0.00000 0.000000000 2
7     0.50000 0.250000000 2 
1     0.13636 0.018594050 3 
2     0.09091 0.008264628 3
3     0.40909 0.167354628 3
4     0.04545 0.002065702 3

共有3个答案

李康安
2023-03-14

如果我理解正确,您希望检测h\u no何时不增加,然后增加。(我将介绍如何解决这个问题,最后有一个独立的函数。)

我们目前只关心h_no列,因此我们可以从数据帧中提取该列:

> h_no <- data$h_no

我们想检测什么时候h_no没有上升,我们可以通过计算连续元素之间的差值是负还是零来实现。R提供了diff函数,该函数为我们提供了差异向量:

> d.h_no <- diff(h_no)
> d.h_no
 [1]  1  1  1 -3  1  1  1  1  1  1 -6  1  1  1

一旦我们有了这个,找到那些非积极的就很简单了:

> nonpos <- d.h_no <= 0
> nonpos
 [1] FALSE FALSE FALSE  TRUE FALSE FALSE FALSE FALSE FALSE FALSE  TRUE FALSE
[13] FALSE FALSE

在R中,TRUEFALSE10基本相同,因此如果我们得到nonpos的累积和,它将在适当的位置增加1(几乎)。cumsum函数(基本上与diff相反)可以做到这一点。

> cumsum(nonpos)
 [1] 0 0 0 1 1 1 1 1 1 1 2 2 2 2

但是,有两个问题:数字太小;我们缺少第一个元素(第一类应该有四个)。

第一个问题简单地解决了:1cumsum(nonpos)。第二个元素只需要在向量的前面添加一个1,因为第一个元素总是在类1中:

 > classes <- c(1, 1 + cumsum(nonpos))
 > classes
  [1] 1 1 1 1 2 2 2 2 2 2 2 3 3 3 3

现在,我们可以使用cbind将其附加回我们的数据帧(通过使用class=语法,我们可以为列提供class标题):

 > data_w_classes <- cbind(data, class=classes)

data\u w\u classes现在包含结果。

我们可以将这些行压缩在一起,并将其全部打包成一个函数,以使其更易于使用:

classify <- function(data) {
   cbind(data, class=c(1, 1 + cumsum(diff(data$h_no) <= 0)))
}

或者,由于作为一个因素是有意义的:

classify <- function(data) {
   cbind(data, class=factor(c(1, 1 + cumsum(diff(data$h_no) <= 0))))
}

您可以使用以下任一函数:

> classified <- classify(data) # doesn't overwrite data
> data <- classify(data) # data now has the "class" column

(解决这个问题的这种方法很好,因为它避免了显式迭代,这通常推荐用于R,并且避免了生成大量中间向量和列表等,而且它在一行上的书写方式也很简洁:))

公良弘毅
2023-03-14

很容易:您的数据帧是一个

b <- A[,1]
b <- b==1
b <- cumsum(b)

然后你得到b栏。

白昊乾
2023-03-14

您可以使用各种技术向数据中添加列。下面的引号来自相关帮助文本的“详细信息”部分,[.data.frame

数据帧可以在几种模式下建立索引。当[[与单个向量索引(x[i]x[[i]])一起使用时,它们将数据帧作为列表进行索引。

my.dataframe["new.col"] <- a.vector
my.dataframe[["new.col"]] <- a.vector

$的data.frame方法将x视为列表

my.dataframe$new.col <- a.vector

[[与两个索引(x[i,j]x[[i,j]])一起使用时,它们就像为矩阵编制索引一样

my.dataframe[ , "new.col"] <- a.vector

因为data.frame方法假设如果不指定使用的是列还是行,它将假设您指的是列。

对于您的示例,这应该工作:

# make some fake data
your.df <- data.frame(no = c(1:4, 1:7, 1:5), h_freq = runif(16), h_freqsq = runif(16))

# find where one appears and 
from <- which(your.df$no == 1)
to <- c((from-1)[-1], nrow(your.df)) # up to which point the sequence runs

# generate a sequence (len) and based on its length, repeat a consecutive number len times
get.seq <- mapply(from, to, 1:length(from), FUN = function(x, y, z) {
            len <- length(seq(from = x[1], to = y[1]))
            return(rep(z, times = len))
         })

# when we unlist, we get a vector
your.df$group <- unlist(get.seq)
# and append it to your original data.frame. since this is
# designating a group, it makes sense to make it a factor
your.df$group <- as.factor(your.df$group)


   no     h_freq   h_freqsq group
1   1 0.40998238 0.06463876     1
2   2 0.98086928 0.33093795     1
3   3 0.28908651 0.74077119     1
4   4 0.10476768 0.56784786     1
5   1 0.75478995 0.60479945     2
6   2 0.26974011 0.95231761     2
7   3 0.53676266 0.74370154     2
8   4 0.99784066 0.37499294     2
9   5 0.89771767 0.83467805     2
10  6 0.05363139 0.32066178     2
11  7 0.71741529 0.84572717     2
12  1 0.10654430 0.32917711     3
13  2 0.41971959 0.87155514     3
14  3 0.32432646 0.65789294     3
15  4 0.77896780 0.27599187     3
16  5 0.06100008 0.55399326     3
 类似资料:
  • 问题内容: 我正在尝试创建一个列(“ consec”),该列将连续计数另一个(“二进制”)中的连续值,而不使用循环。这是预期的结果: 但是这个 导致… 我看到了其他使用分组或排序的帖子,但不幸的是,我看不到如何对我有用。在此先感谢您的帮助。 问题答案: 您可以使用compare-cumsum-groupby模式(我 确实 需要解决这个问题才能编写文档),最后是: 之所以有效,是因为首先我们得到了要

  • 谈到R编码,我目前有点墨守成规。我一直在尝试使用mutate、seq和rep函数来生成一个新列,该列迭代多个列值和不同的条件,但结果并不正确。下面是我的一些数据片段: 我希望按类型和特征 ID 对 lipidName 进行分组,然后查看类型特征 ID2,而不是不正确的数据表。如果它们具有相同的类型和特征 ID,则将它们计为脂质名称的相同脂质。如果它们具有相同的类型和特征ID2,则将它们计为脂质名称

  • 我以前见过一些最长的连续序列问题,比如查找递增子序列。我现在正在努力进一步发展我的技能。给定一个整数数组,我想找到一个最长的连续序列,其中各个子序列中所有元素的差值小于一个给定的数字,例如3。一个例子是[10,11,12,15,13],其中只有前三个元素满足条件。此外,我还想返回给定数组中第一个和最后一个元素的索引。 我想做两个函数;get_first_element(arr)和get_last_

  • 问题内容: 我使用Hibernate4来映射到Postgres数据库。在进行映射之前,我先创建Java实体。然后,我使用一个Java类从我的实体生成sql脚本。这是我的实体: 用户实体 项目实体 我注意到,这会为表myusers和项目产生相同的序列。如果我在myusers表上创建第一条记录,则id将具有“ 1”作为值,然后当我在表项目中创建第一条记录时,该记录将具有id =2。他们使用相同的序列。

  • 我有如下数据集: 这是我们数据库中每个帐户的备忘录集合。“1abc”中的1表示帐户ID,字母表示一些文本。总共有177列和1866行,但并非每行都有177列之前的值,有些行可能只有两列数据。 我需要每一列下拉到A列的底部,以便所有数据只占用A列。例如,B列中的所有数据都将插入A列中的最后一个值之后。C列中的数据将插入A列中的最后一个值之后,它已填充了来自B的数据,依此类推。 最后,它应该是这样的(

  • 该问题给出了两个输入:数组(arr)和由数组构成子数组的次数(n)。子数组的和应该是奇数 已经很清楚,如果所有的数字都是偶数。奇数和子数组是不可能的。对于奇数和,连续的2个数字应该是奇数+偶数或者偶数+奇数。但我似乎不能把它们分成N个子数组。请帮忙解释一下逻辑。