根据特定条件将多行转换为单行

时间:2014-10-31 12:24:01

标签: r

您能否建议如何在R。

中实施以下内容

我有一张桌子如下。

 ID  object  value
  1   a  3
  2   a  2
  3   b  3
  4   a  1
  5   a  2
  6   b  2
  7   a  1
  8   b  1

我想得到下表

 ID object values
 1   a    3, 2, 1
 2   a    2, 1
 4   a    1
 5   a    2, 1
 7   a    1
 3   b    3, 2, 1
 6   b    2,1
 8   b    1

换句话说,对于每个对象,每个行值附加下一个观察值,直到值达到1.

非常感谢你的帮助。

Bikas

2 个答案:

答案 0 :(得分:0)

将修改后的dataset第二行值用作4

res <-  unsplit(lapply(split(df, df$object), function(x) {
                     x$value <- sapply(seq_len(nrow(x)), function(i) {
                                   i1 <- i:nrow(x)
                                   indx <- which(x$value[i1]==1)[1]
                                   paste(x$value[i1[seq(indx)]], collapse=",")
                                       })
                                     x}),
                                  df$object)  


    res[order(res$object),]
    #  ID object   value
    #1  1      a 3, 4, 1
    #2  2      a    4, 1
    #4  4      a       1
    #5  5      a    2, 1
    #7  7      a       1
    #3  3      b 3, 2, 1
    #6  6      b    2, 1
    #8  8      b       1

另外,使用data.table

 library(data.table)
 setDT(df)[, N:=1:.N, by=object][,
          values:=unlist(lapply(N, function(i) {
                                   val <- value[i:.N]
                                   paste(val[1:which(val==1)[1]], collapse=",")
                                  })), keyby=object][,-(3:4), with=FALSE]


   #    ID object values
   #1:  1      a  3,4,1
   #2:  2      a    4,1
   #3:  4      a      1
   #4:  5      a    2,1
   #5:  7      a      1
   #6:  3      b  3,2,1
   #7:  6      b    2,1
   #8:  8      b      1

更新

如果您需要序列到最小value,则可以将which(x$value[i1]==1替换为which(x$value[i1]==min(x$value))[1]。例如,将第一个代码用作函数。

 f1 <- function(dat){
   lst <- split(dat, dat$object)
   lst2 <- lapply(lst, function(x) {
        x$value <- sapply(seq_len(nrow(x)), function(i) {
                     i1 <- i:nrow(x)
                     indx <- which(x$value[i1]== min(x$value))[1]
                     paste(x$value[i1[seq(indx)]], collapse=",")
                        })
                       x})
   res <- unsplit(lst2, dat$object)
   res[order(res$object),] 
  } 

  f1(df)
  #   ID object value
  #1  1      a 3,4,1
  #2  2      a   4,1
  #4  4      a     1
  #5  5      a   2,1
  #7  7      a     1
  #3  3      b 3,2,1
  #6  6      b   2,1
  #8  8      b     1

如果我将所有1值更改为2

  df$value[df$value==1] <- 2
  f1(df)
  #  ID object value
  #1  1      a 3,4,2
  #2  2      a   4,2
  #4  4      a     2
  #5  5      a     2
  #7  7      a     2
  #3  3      b   3,2
  #6  6      b     2
  #8  8      b     2

数据

df <- structure(list(ID = 1:8, object = c("a", "a", "b", "a", "a", 
"b", "a", "b"), value = c(3L, 4L, 3L, 1L, 2L, 2L, 1L, 1L)), .Names = c("ID", 
"object", "value"), class = "data.frame", row.names = c(NA, -8L
))

答案 1 :(得分:0)

是否

并不完全清楚
  • 数据总是按值减少排序
  • 以及值是否应按递减顺序输出

无论如何,我会使用data.table库。假设您的表是data.frame df,我会执行以下操作:

library(data.table)
setDT(df)

df[ values >= 1 ][ by=list( ID, value ), order(value, decreasing=TRUE),  values = paste0( value, sep=", " ) ]

这是做什么的:

  • 将data.frame初始化为data.table
  • 仅使用值为&gt; = 1
  • 的行
  • 订购数据
  • 按ID和值分组
  • 一起粘贴价值