4

对于我做错了什么,可能真的有一个简单的解释,但是我今天已经为此工作了很长一段时间,但我仍然无法让它发挥作用。我认为这将是在公园里散步,但是,我的代码并没有按预期工作。

所以对于这个例子,假设我有一个如下的数据框。

df
Row#   user      columnB    
1        1          NA        
2        1          NA        
3        1          NA        
4        1          31        
5        2          NA        
6        2          NA        
7        2          15        
8        3          18        
9        3          16       
10       3          NA

基本上,我想创建一个新列,它使用第一个(以及最后一个)函数(在 TTR 库包中)为每个用户获取第一个非 NA 值。所以我想要的数据框就是这个。

df
Row#   user      columnB    firstValue
1        1          NA        31
2        1          NA        31 
3        1          NA        31
4        1          31        31
5        2          NA        15
6        2          NA        15 
7        2          15        15
8        3          18        18
9        3          16        18
10       3          NA        18

我主要使用谷歌环顾四周,但我真的找不到我的确切答案。

这是我尝试过的一些代码,但没有得到我想要的结果(注意,我是从记忆中带来的,所以还有很多变体,但这些是一般形式我一直在尝试)。

    df$firstValue<-ave(df$columnB,df$user,FUN=first,na.rm=True)
    df$firstValue<-ave(df$columnB,df$user,FUN=function(x){x,first,na.rm=True})
    df$firstValue<-ave(df$columnB,df$user,FUN=function(x){first(x,na.rm=True)})
    df$firstValue<-by(df,df$user,FUN=function(x){x,first,na.rm=True})

失败了,这些只是给出每个组的第一个值,即 NA。

同样,这些只是我脑海中的几个例子,我玩弄了 na.rm,使用了 na.exclude、na.omit、na.action(na.omit) 等......

任何帮助将不胜感激。谢谢。

4

4 回答 4

4

一个data.table解决方案

require(data.table)
DT <- data.table(df, key="user")
DT[, firstValue := na.omit(columnB)[1], by=user]
于 2013-02-25T15:29:41.217 回答
3

这是一个解决方案plyr

ddply(df, .(user), transform, firstValue=na.omit(columnB)[1])

这使 :

  Row user columnB firstValue
1   1    1      NA         31
2   2    1      NA         31
3   3    1      NA         31
4   4    1      31         31
5   5    2      NA         15
6   6    2      NA         15
7   7    2      15         15
8   8    3      18         18
9   9    3      16         18

如果要捕获最后一个值,可以执行以下操作:

ddply(df, .(user), transform, firstValue=tail(na.omit(columnB),1))
于 2013-02-25T15:34:20.450 回答
3

使用data.table

library (data.table)
DT <- data.table(df, key="user")
DT <- setnames(DT[unique(DT[!is.na(columnB), list(columnB), by="user"])], "columnB.1", "first")
于 2013-02-25T15:38:46.543 回答
2

使用一个非常小的辅助函数

finite <- function(x) x[is.finite(x)]

这是一个仅使用标准 R 函数的单行代码:

df <- cbind(df, firstValue = unlist(sapply(unique(df[,1]), function(user) rep(finite(df[df[,1] == user,2])[1], sum(df[,1] == user))))

为了更好地概述,这里是展开成“多线”的单线:

# for each user, find the first finite (in this case non-NA) value of the second column and replicate it as many times as the user has rows
# then, the results of all users are joined into one vector (unlist) and appended to the data frame as column
df <- cbind(
  df,
  firstValue = unlist(
    sapply(
       unique(df[,1]),
       function(user) {
         rep(
           finite(df[df[,1] == user,2])[1],
           sum(df[,1] == user)
         )
       }
    )
  )
)
于 2013-02-25T15:47:26.513 回答