• R语言
  • 如何查找数据首次非0等问题

试一下这个

col <- apply(x, 1, function(x) which(x>0)[1] )

colnames(x)[col]

<br />
  x <- matrix(0,5 ,10)<br />
  x[sample(50, 20)] <- sample(50, 20)<br />
  colnames(x) <- as.character(seq(as.Date("2010/1/1"), as.Date("2010/1/10"), "day"))<br />
  x<br />
  2010-01-01 2010-01-02 2010-01-03 2010-01-04 2010-01-05 2010-01-06 2010-01-07<br />
  [1,]          0         42         49          0          0         50          0<br />
  [2,]          0          0          0          0         17         13          0<br />
  [3,]          0          0         21         18          0          9          0<br />
  [4,]          2          0          0         31          0          0          0<br />
  [5,]          0         39         11          0          0         25          0<br />
  2010-01-08 2010-01-09 2010-01-10<br />
  [1,]         35         28         19<br />
  [2,]          0         10          0<br />
  [3,]         37         15          0<br />
  [4,]          6          0          0<br />
  [5,]          0          0          0<br />
  col <- apply(x, 1, function(x) which(x>0)[1] )<br />
  colnames(x)[col]<br />
  [1] "2010-01-02" "2010-01-05" "2010-01-03" "2010-01-01" "2010-01-02"</p>
<p>
</p>

回复 第1楼 的 Davidhust:在R里看到这种编程基本上就能认定非常慢了,在R中是很少出现这种底层语言的控制流的

用match也可以

<br />
ff <- function(x) match(TRUE ,x != 0)<br />
test1 <- apply(x, 1, ff)<br />


90万条数据就是瞬间

and

最后一天大于零的话,把向量rev就可以了
</p>

回复 第2楼 的 Robert_Hoo:

谢谢!我的消费数据是从第4列开始的,按照您的语句,



g_char<-apply(g, 1, function(g) which(g[,4:21]>0)[1])

但出现提示:错误于g[, 4:21] : 量度数目不对
</p>

另外我想把首次消费日期做成变量,直接加到原数据新列里,如何实现呢?

回复 第4楼 的 刘思喆:

谢谢,我也是最近看到一些R书籍说要尽量避免循环,可是太菜了,不会写这么精妙的语句[s:12]

关于向量rev,能方便举个例子么?谢谢!

sort(x) 升序排列x中的元素;降序排列使用:rev(sort(x))

回复 第7楼 的 zggjtsgzczh:方法很多,降序可以直接sort(x,decreasing=TRUE)

回复 第5楼 的 Davidhust:你的code在卖萌么。。建议你看看function的用法,你要的应该是这个吧:

g_char<-apply(g[,4;21], 1, function(g) which(g>0)[1])<br />


不过你有第21列么。。。
</p>

回复 第9楼 的 superdesolator:冒号打成分号了。.......

10 天 后

在诸位大神指点下,首次消费日期和最后消费日期的问题已解决,多谢@Robert_Hoo,@刘思喆,@zggjtsgzczh,@superdesolator [s:11]

现在有个新问题,在有了首次消费日期后,如何计算从首次消费日开始,连续7天的消费值的和呢?

即从首列非0起,连续加7列数据,感觉apply和function依然可以用,但苦于不知如何下手,请指教[s:16]

回复 第12楼 的 Davidhust:下面的代码,参考了吧里一些大神给的思路,由于2楼的大神代码的x是随机的,为了让大家看得更清楚,我在有些关键地方,显示出了一些变量的值,因而使得代码略长:

R>x <- matrix(0,5 ,10)<br />
R>  x[sample(50, 20)] <- sample(50, 20)<br />
R>  colnames(x) <- as.character(seq(as.Date("2010/1/1"), as.Date("2010/1/10"), "day"))<br />
R>x<br />
     2010-01-01 2010-01-02 2010-01-03 2010-01-04 2010-01-05 2010-01-06<br />
[1,]         27         19          0          0         35          0<br />
[2,]          0          0         26          0          0          0<br />
[3,]          0         23         41          5          0          0<br />
[4,]          0         44         21          0          0          0<br />
[5,]          0          0          9          6         10          0<br />
     2010-01-07 2010-01-08 2010-01-09 2010-01-10<br />
[1,]         37          1          0          0<br />
[2,]         49          0          0         12<br />
[3,]         43         24          0         46<br />
[4,]          0          0          0          0<br />
[5,]         31          0          0          0<br />
R> col <- apply(x, 1, function(x) which(x>0)[1] )<br />
R>col<br />
[1] 1 3 2 2 3<br />
R>col1=col+1;col2=col+2;col3=col+3;col4=col+4;col5=col+5;col6=col+6;<br />
R>dt=cbind(col,col1,col2,col3,col4,col5,col6)<br />
R>dt<br />
     col col1 col2 col3 col4 col5 col6<br />
[1,]   1    2    3    4    5    6    7<br />
[2,]   3    4    5    6    7    8    9<br />
[3,]   2    3    4    5    6    7    8<br />
[4,]   2    3    4    5    6    7    8<br />
[5,]   3    4    5    6    7    8    9<br />
R>b=rep(1:nrow(dt),each=ncol(dt))<br />
R>d=cbind(b,as.numeric(t(dt)))<br />
R>d<br />
      b<br />
 [1,] 1 1<br />
 [2,] 1 2<br />
 [3,] 1 3<br />
 [4,] 1 4<br />
 [5,] 1 5<br />
 [6,] 1 6<br />
 [7,] 1 7<br />
 [8,] 2 3<br />
 [9,] 2 4<br />
[10,] 2 5<br />
[11,] 2 6<br />
[12,] 2 7<br />
[13,] 2 8<br />
[14,] 2 9<br />
[15,] 3 2<br />
[16,] 3 3<br />
[17,] 3 4<br />
[18,] 3 5<br />
[19,] 3 6<br />
[20,] 3 7<br />
[21,] 3 8<br />
[22,] 4 2<br />
[23,] 4 3<br />
[24,] 4 4<br />
[25,] 4 5<br />
[26,] 4 6<br />
[27,] 4 7<br />
[28,] 4 8<br />
[29,] 5 3<br />
[30,] 5 4<br />
[31,] 5 5<br />
[32,] 5 6<br />
[33,] 5 7<br />
[34,] 5 8<br />
[35,] 5 9<br />
R>dta=matrix(x[d],nrow(dt),byrow=TRUE)<br />
R>dta<br />
     [,1] [,2] [,3] [,4] [,5] [,6] [,7]<br />
[1,]   27   19    0    0   35    0   37<br />
[2,]   26    0    0    0   49    0    0<br />
[3,]   23   41    5    0    0   43   24<br />
[4,]   44   21    0    0    0    0    0<br />
[5,]    9    6   10    0   31    0    0<br />
R>sum1=apply(dta,MARGIN=1,FUN=sum)<br />
R>sum1<br />
[1] 118  75 136  65  56<br />
R>
</p>

回复 第13楼 的 superdesolator:

谢谢@superdesolator

大概明白是抽取出符合要求的列,再求和

但没看懂如何把这些列给抽出来的

每一步是什么意思?

从col1=col+1;col2=col+2;col3=col+3;col4=col+4;col5=col+5;col6=col+6开始就看不懂了[s:12]

求指教

回复 第14楼 的 Davidhust:col返回首列非0,+1,。。。,+6,组成的dt矩阵,返回连续7天的数据所在的列,后面就是根据行,列,去X里提取数据了。

回复 第15楼 的 superdesolator:

b=rep(1:nrow(dt),each=ncol(dt))

d=cbind(b,as.numeric(t(dt)))

b,d在此过程中有什么作用?

回复 第15楼 的 superdesolator:

以及,我按照您的代码,做到这一步,

dta<-matrix(x[d],nrow(dt),byrow=TRUE)

出来“错误于as.matrix(x) : 下标出界”

不知是怎么回事啊?[s:16]

x 是 78042 obs. of 370 variables(其中第3:368是消费数据)

dt 是 78042×7 double matrix

d 是 546294×2 double matrix


回复 第17楼 的 Davidhust:没想到54W行就不行了么.......这个需要大神来改进我的方法了,我只能给你解释下b,d:

比如x=

1 3

2 4

这样一个2*2的矩阵,那么我要提取它的第1行,第2列的值该怎么办?

R>b

[,1] [,2]

[1,] 1 2

x就行了

同样的道理,我有1个5*7的矩阵dt,dt中的第1行的第1列的值,是不是就是原数据x中的第1行的,首次非0列的列数啊,dt列的第1行第7列的值是不是就是x中第1行首次非0列连续之后的第7列的列数呢。

有了上面的对应关系,如何提取x中第1行对应的那7列的值呢(上面只知道所在的第1行和第几列,没有返回值)

前面已经举了个例子,那么为了实现我一下提取7个,是不是要有一个这样的表达式:

x=x[d],其中d为:

1 1

1 2

1 3

...

1 7

同样的道理对于第2行,我们得有1个d

2 3

2 4

。。

2 9

b=rep(1:nrow(dt),each=ncol(dt)),

d=cbind(b,as.numeric(t(dt)))

就是干了这个事情,它把所有的d接在了一起(你需要看下rep的用法)

那这样得到的b是不是就是所有我们需要的值了,它还只是个向量

怎么还原成矩阵呢:dta<-matrix(x[d],nrow(dt),byrow=TRUE)


我注意到一个问题可能产生越界,就是,比如一个人在第363—368天首次消费,那么显然我上面的算连续7天的列数的话,出来的列数会超过370列,出现错误。

6 天 后

回复 第19楼 的 superdesolator:

多谢@superdesolator,果然只计算到第362列,不计算363-368,就可以了[s:11]



col<-apply(x[,3:362], 1, function(x) which(x>0)[1])


但有个问题,得到的dta矩阵,缺乏x第一列的客户ID,没法进行下一步工作了,该肿么办呢?[s:12]
</p>