【问题标题】:Applying functions to multiple lists将函数应用于多个列表
【发布时间】:2014-03-03 17:01:58
【问题描述】:

我正在尝试在具有销售分类变量的数据框上运行一些基本统计数据(以及以后更深入的统计数据)。除了销售额之外,它还跟踪区域(商家所在的位置)、星期几、一天中的时间(午餐、下班后等)以及其他各种信息。

这是一个小的随机数据子集:(请注意,这是一个基本表示 - 实际数据框有 38 列 - 我只是去掉了大部分不适用的列)

    structure(list(dayofweek = structure(c(4L, 7L, 3L, 7L, 3L, 2L, 
2L, 7L, 3L, 3L, 2L, 7L, 5L, 5L, 2L, 5L, 1L, 3L, 7L, 3L, 4L, 1L, 
3L, 5L, 7L), .Label = c("Friday", "Monday", "Saturday", "Sunday", 
    "Thursday", "Tuesday", "Wednesday"), class = "factor"), timeofday = structure(c(6L, 
4L, 5L, 5L, 2L, 6L, 6L, 5L, 6L, 3L, 6L, 3L, 5L, 4L, 1L, 3L, 5L, 
6L, 5L, 4L, 6L, 6L, 3L, 2L, 5L), .Label = c("After Work", "Early AM", 
     "Evening", "Late AM", "Lunch", "MidAfternoon", "Overnight"), class = "factor"), 
 area = c(6L, 4L, 4L, 5L, 5L, 1L, 4L, 2L, 3L, 2L, 7L, 3L, 
 7L, 5L, 7L, 4L, 1L, 4L, 1L, 4L, 5L, 7L, 1L, 3L, 7L), totsales = c(40, 
 6, 5, 10, 1, 0, 0, 3, 5, 3, 10, 30, 2, 1, 2, 22, 8, 1, 1, 
 5, 11, 20, 0, 1, 5)), .Names = c("dayofweek", "timeofday", 
     "area", "totsales"), class = "data.frame", row.names = c(192278L, 
     140773L, 121051L, 157984L, 154299L, 258034L, 108031L, 43760L, 
     78005L, 42103L, 95603L, 98431L, 30252L, 165303L, 40713L, 108252L, 
     304549L, 137041L, 268473L, 124599L, 161253L, 12897L, 240815L, 
     89439L, 21032L))

我要做的第一件事是尝试获取每个区域和一天中每个时间的平均销售额和中位数销售额。我想让 R 遍历每个列表并返回所有值。我试过这个:

vallist<-list(a= c("Early AM", "Late AM", "Lunch", "MidAfternoon", "After Work", 
         "Evening", "Overnight"),
          b= c(1,2,3,4,5,6,7))

sapply(vallist[['b']], function(x)
    mapply(function(a,b) mean(data$totsales[which(data$timeofday==a & data$area==b)]),
          vallist[['a']], vallist[['b']])
 )

但是,它仅将平均值应用于区域 1 中的每个时间段,而不是区域 1-7 中的每个时间段。所以,我的结果是这样的:

                  [,1]      [,2]      [,3]      [,4]      [,5]      [,6]      [,7]
Early AM      9.192847  9.192847  9.192847  9.192847  9.192847  9.192847  9.192847
Late AM       8.020678  8.020678  8.020678  8.020678  8.020678  8.020678  8.020678
Lunch        10.096277 10.096277 10.096277 10.096277 10.096277 10.096277 10.096277
MidAfternoon 11.503961 11.503961 11.503961 11.503961 11.503961 11.503961 11.503961
After Work    8.206124  8.206124  8.206124  8.206124  8.206124  8.206124  8.206124
Evening      11.457599 11.457599 11.457599 11.457599 11.457599 11.457599 11.457599
Overnight    11.415667 11.415667 11.415667 11.415667 11.415667 11.415667 11.415667

这是区域 1 的正确答案,但您可以看到它们对于每个区域都是相同的值。如何让 R 将函数应用于多个列表并返回所有值组合?

接下来的步骤将是应用中位数,并在地区级别和不同的工作日进行评估,但我认为相同的想法将适用于所有不同的组合。

【问题讨论】:

  • 您只是在寻找aggregate吗?可能是aggregate(totsales ~ timeofday + area, data, mean) 之类的东西?
  • 是的,这绝对有效。我倾向于使事情变得比 R 中需要的要复杂得多……我想这与它的初学者有关。谢谢!不过,为了将来的参考,我仍然想知道为什么上面的代码不能通读列表。
  • @AnandaMahto,如果你的时间安排得当,你应该在 SO 的第 50Kth [r] 问题上获得 50K 代表。这至少值得 10K 奖金代表。
  • @datahappy,将mapply 中的vallist[['b']] 更改为x,然后您将得到与我所做的大致相同的结果(大致是因为您也需要na.rm )。

标签: r sapply mapply


【解决方案1】:

对于这种特殊情况,您可以使用以下方法重现您的结果:

library(reshape2)
dcast(data[-1], timeofday ~ area, fun.aggregate=mean, fill=0)

产生:

     timeofday   1 2  3    4  5  6    7
1   After Work 0.0 0  0  0.0  0  0  2.0
2     Early AM 0.0 0  1  0.0  1  0  0.0
3      Evening 0.0 3 30 22.0  0  0  0.0
4      Late AM 0.0 0  0  5.5  1  0  0.0
5        Lunch 4.5 3  0  5.0 10  0  3.5
6 MidAfternoon 0.0 0  5  0.5 11 40 15.0

我很确定与您的结果的差异是由于您发布的数据是整体的子集。

【讨论】:

  • 是的,谢谢。我知道这不需要它,但是知道为什么上面的代码只应用了列表“b”中的第一个值吗?需要改变什么才能让它在列表 'b' 中的值 1-7 之间循环,就像它对列表 'a' 所做的那样?
  • @datahappy,请参阅我对您的问题的新评论。
  • +1。如果他们对aggregate 做出肯定的回应,我是否还有其他计划。
【解决方案2】:

将我的评论转换为答案....

您似乎对aggregate 感兴趣(尽管有许多种方法可以在 R 中聚合数据)。

out <- aggregate(totsales ~ timeofday + area, data, mean)
out
#       timeofday area totsales
# 1       Evening    1      0.0
# 2         Lunch    1      4.5
# 3  MidAfternoon    1      0.0
# 4       Evening    2      3.0
# 5         Lunch    2      3.0
# 6      Early AM    3      1.0
# 7       Evening    3     30.0
# 8  MidAfternoon    3      5.0
# 9       Evening    4     22.0
# 10      Late AM    4      5.5
# 11        Lunch    4      5.0
# 12 MidAfternoon    4      0.5
# 13     Early AM    5      1.0
# 14      Late AM    5      1.0
# 15        Lunch    5     10.0
# 16 MidAfternoon    5     11.0
# 17 MidAfternoon    6     40.0
# 18   After Work    7      2.0
# 19        Lunch    7      3.5
# 20 MidAfternoon    7     15.0

如果您想从那里转到宽格式,则可以使用reshape(例如:reshape(out, direction = "wide", idvar="timeofday", timevar="area"))。

【讨论】:

    猜你喜欢
    • 2021-08-09
    • 2022-10-14
    • 1970-01-01
    • 2013-01-09
    相关资源
    最近更新 更多