根据两列拆分数据帧,并对子组应用一些操作

时间:2018-12-17 14:46:46

标签: python pandas group-by

我的数据框如下:

Short View of Data

PlantProduct中的一个项目(表示植物);可以有多个物料编号  我想做什么:

  1. 根据PlantProduct和MaterialNumber对数据框进行分组,换句话说,将它们拆分为数据框。
  2. 如果组成员的元素长度小于10,则将其删除
  3. 因此,在工作结束时,我应该有一种仅包含此类数据框的列表元素:

grouped data

  1. 有了这些数据帧之后,我将执行更多其他操作;例如图表,以及整个列表元素的时间序列预测(如图-2所示)

我所做的是以下事情:

      df.groupby(by=['PlantProduct','MaterialNumber']).apply(lambda x:len(x)>10)

但是,此脚本创建了一个分组的数据框对象,我无法对其执行任何操作。

为了帮助我在这里写下我的脚本,但是我也必须在python中完成它,因为您可能会猜测我不是python专家。

我的R代码:

#split 1st due to PlantProduct

    mylist <- split(res2, res2$PlantProduct)

#second split due to MaterialNumber

      for(name in names(mylist))
      mylist[[name]] <- split(mylist[[name]], mylist[[name]]["MaterialNumber"])
      mylist[[name]] <- mylist[[name]][sapply(mylist[[name]], function(x) nrow(x)[[1]]) > 10]
    } 

#Encoding 0 values with NA, all over the list elements

    for(name in names(mylist)) {
      for(name2 in names(mylist[[name]]))
      {
        mylist[[name]][[name2]][,4] <- ifelse(mylist[[name]][[name2]][,4] == 0, NA, mylist[[name]][[name2]][,4])
      }
    }

#creating a date index column and joining it with the list element

    for(name in names(mylist)) {
      for(name2 in names(mylist[[name]]))
      {
        mydate <- data.frame(seq(min(as.Date(mylist[[name]][[name2]][,3])), as.Date('2018-05-01'), by = "month"))
        colnames(mydate) <- "ds"
        mylist[[name]][[name2]] <- left_join(mydate, mylist[[name]][[name2]], "ds")
        rm(mydate)
      }
    }

#time series forecasting on individual list elements

    for(name in names(mylist)) {
      for(name2 in names(mylist[[name]]))
      {
      m <- prophet(mylist[[name]][[name2]])
      future <- make_future_dataframe(m, periods = 1, freq = "month")
      forecast <- predict(m, future)
      a <- data.frame(tail(forecast[c('ds', 'yhat', 'yhat_lower', 'yhat_upper')], n = 365))
      a$ds <- as.Date(a$ds, "%Y-%m-%d")
      mylist[[name]][[name2]] <- left_join(a, mylist[[name]][[name2]], "ds")
      rm(m, future, forecast, a)
      }
    }

2 个答案:

答案 0 :(得分:2)

为了GroupBy并保留原始结构,请改为从文档中使用filter

  

返回DataFrame的副本,其中不包括不满足func指定的布尔条件的组中的元素。

因此,请这样做:

df.groupby(['PlantProduct', 'MaterialNumber']).filter(lambda x: len(x) > 10)

这是一个玩具示例:

df = pd.DataFrame({'a':[1,1,1,1,1,1,1], 'b':[2,2,2,3,3,3,1]})

使用apply

df.groupby(['a', 'b']).apply(lambda x: len(x) >= 2)

a  b
1  1    False
   2     True
   3     True
dtype: bool

在您应用条件时,这将为每个组返回一组booleans

但是,使用filter时,此条件的结果将用于过滤原始数据帧:

df.groupby(['a', 'b']).filter(lambda x: len(x) >= 2)

   a  b
0  1  2
1  1  2
2  1  2
3  1  3
4  1  3
5  1  3

答案 1 :(得分:0)

您可以使用transform

df=df[df.groupby(['PlantProduct', 'MaterialNumber']).PlantProduct.transform('count')>10]

尼克松的测试框架

df[df.groupby(['a','b']).a.transform('count')>2]
Out[203]: 
   a  b
0  1  2
1  1  2
2  1  2
3  1  3
4  1  3
5  1  3