根据一列中的不同值同时创建多个数据帧

时间:2014-06-01 17:50:02

标签: r dataframe subset

我想根据列中的值创建多个数据帧。

  

样本数据

df
Index Product ID Amount
200   Prod1   01 100
201   Prod1   01 150
202   Prod1   01 123
203   Prod1   01 123
204   Prod1   02 110
205   Prod1   02 175
206   Prod1   02 190
207   Prod2   03 120
208   Prod2   03 135
209   Prod2   03 150

我想为每个ID添加一列作为Base。 Base的值是每个ID中的第一个金额值。

>df1
Index Product ID Amount Base
200   Prod1   01 100    100
201   Prod1   01 150    100
202   Prod1   01 123    100
203   Prod1   01 123    100
204   Prod1   02 110    110
205   Prod1   02 175    110
206   Prod1   02 190    110
207   Prod2   03 120    120
208   Prod2   03 135    120
209   Prod2   03 150    120

我正在考虑首先通过ID对df进行子集化。只是想知道是否有任何方法可以做到这一点?

5 个答案:

答案 0 :(得分:7)

您可以创建数据框列表,然后使用list2env

将它们嵌入到您想要的任何环境中
SubData <- lapply(unique(df$ID), function(x) cbind(df[df$ID == x, ], Base = df$Amount[df$ID == x][1]))


# [[1]]
#   Index Product ID Amount Base
# 1   200   Prod1  1    100  100
# 2   201   Prod1  1    150  100
# 3   202   Prod1  1    123  100
# 4   203   Prod1  1    123  100
# 
# [[2]]
#   Index Product ID Amount Base
# 5   204   Prod1  2    110  110
# 6   205   Prod1  2    175  110
# 7   206   Prod1  2    190  110
# 
# [[3]]
#    Index Product ID Amount Base
# 8    207   Prod2  3    120  120
# 9    208   Prod2  3    135  120
# 10   209   Prod2  3    150  120

现在为您的数据框提供您想要的任何名称,并使用list2env在环境中创建它们

names(SubData) <- c("df1", "df2", "df3")
list2env(SubData, envir = .GlobalEnv)

现在,您可以在全球环境中拥有这些数据集,例如

df1
##   Index Product ID Amount Base
## 1   200   Prod1  1    100  100
## 2   201   Prod1  1    150  100
## 3   202   Prod1  1    123  100
## 4   203   Prod1  1    123  100

答案 1 :(得分:4)

使用ave

dat$Base <- ave(dat$Amount,dat$ID,FUN=min)

# Index Product ID Amount Base
# 1    200   Prod1  1    100  100
# 2    201   Prod1  1    150  100
# 3    202   Prod1  1    123  100
# 4    203   Prod1  1    123  100
# 5    204   Prod1  2    110  110
# 6    205   Prod1  2    175  110
# 7    206   Prod1  2    190  110
# 8    207   Prod2  3    120  120
# 9    208   Prod2  3    135  120
# 10   209   Prod2  3    150  120

修改

如果你想要第一个值和最小值:

dat$Base <- ave(dat$Amount,dat$ID,FUN=function(x)x[1])

答案 2 :(得分:3)

假设您的data.frame被称为dat,这是一个data.table解决方案:

require(data.table)
setDT(dat)[, Base := Amount[1L], by=ID]
#    Index Product ID Amount Base
#  1:   200   Prod1  1    100  100
#  2:   201   Prod1  1    150  100
#  3:   202   Prod1  1    123  100
#  4:   203   Prod1  1    123  100
#  5:   204   Prod1  2    110  110
#  6:   205   Prod1  2    175  110
#  7:   206   Prod1  2    190  110
#  8:   207   Prod2  3    120  120
#  9:   208   Prod2  3    135  120
# 10:   209   Prod2  3    150  120

答案 3 :(得分:2)

您可以使用dplyr创建Base列,但为了清楚起见,这还没有创建不同的data.frames(如您的问题所示)。

require(dplyr)

df <- df %.% group_by(ID) %.% mutate(Base = first(Amount))

答案 4 :(得分:1)

或使用dplyr

library(dplyr)
df1 <- df %>% 
  arrange(ID, Amount) %>%
  group_by(ID) %>% 
  mutate(Base = Amount[1])