【问题标题】:manipulation of data in R using data.table or dplyr with groupby and subsetting of dates使用带有 groupby 和日期子集的 data.table 或 dplyr 在 R 中操作数据
【发布时间】:2016-11-20 02:39:37
【问题描述】:

我正在寻求有关 data.table 和/或 dplyr 的帮助。我有一个这样的数据框:

Name     Date          X      Y
Mike     2016-10-21    3.2    1.6
Mike     2016-10-23    3.1    1.4
Mike     2016-10-24    4.9    3.8
Mike     2016-10-25    5.7    4.2
Mike     2016-10-28    0.2   -1.1
Bob      2016-10-21    2.2   -1.1
Bob      2016-10-22    0.2   -3.6
Bob      2016-10-24   -9.2  -14.1
Bob      2016-10-25   -7.2  -12.1
Alice    2016-10-20    7.2    6.1
Alice    2016-10-21    2.2    0.1
Alice    2016-10-23   13.2    8.1
Alice    2016-10-25   12.6    8.8
Alice    2016-10-27    7.7    4.7
Alice    2016-10-28    8.2    5.0

我希望能够返回每个人的 X 和 Y 的平均值,但是,我想对其进行子集化,以便它只使用每个人最近 3 个日期的值,而忽略旧日期的数据。我还想返回这 3 个最近日期之间的天数。理想情况下,我最终会得到这样的数据框:

Name     DaysBetween   avgX    avgY
Mike               4    3.6     2.3
Bob                3   -5.4    -9.9
Alice              3    9.5     6.2

编辑说明:此数据将始终按日期排序,因此我们也可以只获取每个人的“最后 3 个”数据点,而不是尝试使用日期逻辑来查找最近的三个数据点。

提前感谢您的帮助!

【问题讨论】:

  • 嗯,你有没有尝试过任何产生错误或错误结果的方法?
  • 不,我没有。到目前为止,我只能获得每个人所有数据点的 X 和 Y 平均值。但我正在努力解决如何仅使用 3 个最近的日期进行子集化。不过,我是 data.table 和 dplyr 的菜鸟。

标签: r data.table dplyr


【解决方案1】:

我们可以使用data.table

library(data.table)
setDT(df1)[order(-Date), .(DaysBetween = as.integer(Date[1L] - Date[3L]), 
         avgX = mean(X[1:3]), avgY = round(mean(Y[1:3]),2)), by  = Name]
#    Name DaysBetween avgX  avgY
#1:  Mike           4  3.6  2.30
#2: Alice           3  9.5  6.17
#3:   Bob           3 -5.4 -9.93

【讨论】:

  • 感谢您的回复。这也很有效!
【解决方案2】:

以上都是很好的回应,这里是一个迭代的方法:

#initialize the output frame
outputFrame = as.data.frame(matrix(nrow = length(unique(train$Name)),
ncol = 4))

#renaming the data frame
names(outputFrame) = c("Names", "daysBetween", "avgX", "avgY")

#turn the date to a date
train$Date = as.Date(train$Date, "%m/%d/%Y")

#initialize the outputCounter
outputCounter = 1

#iterates over every unique Name in the data frame
for(name in as.character(unique(train$Name)))
{
    #subsets the dataframe into the values of each given level of Name
    dfSubset = train[which(train$Name == name),]

    #Orders the dataframe by date
    dfSubset = dfSubset[order(dfSubset$Date),]

    #get the 3 most recent dates
    dfSubset = dfSubset[(nrow(dfSubset) -2):nrow(dfSubset),]

    #fill the names
    outputFrame$Names[outputCounter] = name

    #fill the days between
    outputFrame$daysBetween[outputCounter] = as.numeric(max(dfSubset$Date) - min(dfSubset$Date))

    #get the average X
    outputFrame$avgX[outputCounter] = mean(dfSubset$X)

    #get the average Y
    outputFrame$avgY[outputCounter] = mean(dfSubset$Y)

    #increment outputCounter
    outputCounter = outputCounter +1
}

假设 train 是您的数据框

【讨论】:

    【解决方案3】:

    您可以使用dplyr::top_n 过滤数据:

    library(dplyr)
    
    df %>% mutate(Date = as.Date(Date)) %>%    # parse to Date class, if not already
        group_by(Name) %>% 
        top_n(3, Date) %>%    # filter to max 3 dates for each group
        summarise(DaysBetween = max(Date) - min(Date), 
                  avgX = mean(X), 
                  avgY = mean(Y))
    
    ## # A tibble: 3 × 4
    ##     Name DaysBetween  avgX      avgY
    ##   <fctr>      <time> <dbl>     <dbl>
    ## 1  Alice      3 days   9.5  6.166667
    ## 2    Bob      3 days  -5.4 -9.933333
    ## 3   Mike      4 days   3.6  2.300000
    

    【讨论】:

      猜你喜欢
      • 2014-02-20
      • 1970-01-01
      • 2020-02-06
      • 2018-07-24
      • 2018-11-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多