5

2つ続けて質問するのは本当に嫌いですが、これは頭を抱えることができないものです。したがって、次のようにデータフレームがあるとします。

   df
   Row# User    Morning     Evening     Measure Date
   1    1          NA          NA          2/18/11
   2    1          50          115         2/19/11
   3    1          85          128         2/20/11
   4    1          62          NA          2/25/11
   5    1          48          100.8        3/8/11
   6    1          19          71          3/9/11
   7    1          25          98          3/10/11
   8    1          NA          105         3/11/11
   9    2          48          105         2/18/11
   10   2          28          203         2/19/11
   11   2          35          80.99        2/21/11
   12   2          91          78.25        2/22/11

Rで、ユーザーグループごとに1行の前日の連続した日(および前日のみ、前の結果ではない)の夕方の値と異なる行の朝の値の差をとることは可能ですか?だから私の望ましい結果はこれでしょう。

   df
   Row# User    Morning     Evening     Date        Difference
   1       1      NA          NA        2/18/11        NA
   2       1      50          115       2/19/11        NA
   3       1      85          129       2/20/11        30
   4       1      62          NA        2/25/11        NA
   5       1      48          100.8     3/8/11         NA
   6       1      19          71        3/9/11         81.8
   7       1      25          98        3/10/11        46
   8       1      10          105       3/11/11        88
   9       2      48          105       2/18/11        NA
   10      2      28          203       2/19/11        77
   11      2      35          80.99     2/21/11        NA
   12      2      91          78.25     2/22/11        -10.01

これを実行したいのは、各ユーザーグループの朝の値を取得し、前日の連続した日の夕方の値から減算することだけです。ご覧のとおり、データフレームの一部には、朝と夕方の列にNA値が含まれています。さらに、すべての日付が異なるユーザーごとに連続しているわけではないため、当然、NAを割り当てる必要があります。

私はグーグルを検索しようとしましたが、異なる列の行のグループごとに異なる行に関数を適用できることについての情報はあまりありませんでした(それが理にかなっている場合)。

私の試みには、これの多くのバリエーションが含まれています。

df$Difference<-ave((df$Morning,df$Evening),
                    df$User,
                    FUN=function(x){
                        c('NA',diff(df$Evening-df$Morning)),na.rm=T
                   })

繰り返しになりますが、どんな助けでも大歓迎です。ありがとう。

4

3 に答える 3

4

ブラインドファーストショット(未テスト)。ユーザーと日付で既にソートされているデータフレームに依存します。

#if necessary, transform your dates from factor to Date
df$Date <- as.Date(levels(df$Date)[df$Date],format="%m/%d/%y")

df <- within(df, 
  Difference <- ifelse(c(NA,diff(Measure_Date)) == 1 & diff(User) == 0, 
    c(NA,head(Evening,-1)) - Morning, NA
  )
)
于 2013-02-26T12:57:39.783 に答える
4

注:表示される入力データと出力データは同じではありません。NA出力で置き換えられる があり10、最後の日付は2/14/11入力と2/22/11出力にあります。

結果に一致するようにこの回答を作成するために、出力が元のデータであると想定しました。

df$Diff <- c(NA, head(df$Evening, -1) - tail(df$Morning, -1))
df$Diff[which(c(0, diff(as.Date(as.character(df$Measure_Date), 
                 format="%m/%d/%Y"))) != 1)] <- NA

> df

#    Row User Morning Evening Measure_Date   Diff
# 1    1    1      NA      NA      2/18/11     NA
# 2    2    1      50  115.00      2/19/11     NA
# 3    3    1      85  128.00      2/20/11  30.00
# 4    4    1      62      NA      2/25/11     NA
# 5    5    1      48  100.80       3/8/11     NA
# 6    6    1      19   71.00       3/9/11  81.80
# 7    7    1      25   98.00      3/10/11  46.00
# 8    8    1      10  105.00      3/11/11  88.00
# 9    9    2      48  105.00      2/18/11     NA
# 10  10    2      28  203.00      2/19/11  77.00
# 11  11    2      35   80.99      2/21/11     NA
# 12  12    2      91   78.25      2/22/11 -10.01

@ user1342086 の編集 (拒否されましたが、実際には正しかった):

df$Diff[which(diff(df$User) != 0)] <- NA

「ユーザー」によるグループ化を処理しているようです。

于 2013-02-26T12:59:10.543 に答える
2

を使用plyrしたので、必ずインストールしてください。このソリューションは、ユーザー データが混在していて (つまり、連続した行にない)、日付が時系列に並んでいない場合でも機能するはずです。

# Your example data, as you should post it for us to use
df <-
structure(list(User = c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 
2L, 2L), Morning = c(NA, 50L, 85L, 62L, 48L, 19L, 25L, NA, 48L, 
28L, 35L, 91L), Evening = c(NA, 115, 128, NA, 100.8, 71, 98, 
105, 105, 203, 80.99, 78.25), Measure_Date = structure(c(1L, 
2L, 3L, 5L, 9L, 10L, 6L, 7L, 1L, 2L, 4L, 8L), .Label = c("2/18/11", 
"2/19/11", "2/20/11", "2/21/11", "2/25/11", "3/10/11", "3/11/11", 
"3/14/11", "3/8/11", "3/9/11"), class = "factor")), .Names = c("User", 
"Morning", "Evening", "Measure_Date"), class = "data.frame", row.names = c(NA, 
-12L))

# As already stated by Arun, you need the date as class Date
df$Measure_Date <- as.Date(df$Measure_Date, format='%m/%d/%y')


# Use plyr to procces the dataframe by user
library(package=plyr)
ddply(.data=df, .variables='User',
      .fun=function(x){
        # Complete sequence of dates for each user
        tdf <- data.frame(Measure_Date=seq(from=min(x$Measure_Date),
                                           to=max(x$Measure_Date),
                                           by='1 day'))

        # Merge to fill in NAs for unused dates
        tdf <- merge(tdf, x, all=TRUE)

        # Put desired values side by side
        tdf$Evening <- c(NA, tdf$Evening[-length(tdf$Evening)])

        # Diference
        tdf$Difference  <- tdf$Evening - tdf$Morning

        # Return desired value to original data
        tdf <- tdf[,c('Measure_Date', 'Difference')]
        x <- merge(x, tdf)
        x
      })
于 2013-02-26T13:35:29.000 に答える