将ID变量值替换为值出现次数

时间:2017-09-28 18:30:39

标签: r dataframe replace

我有一个数据框,如:

      DATE    x       y    ID
06/10/2003  7.21    0.651   1
12/10/2003  5.99    0.428   1
18/10/2003  4.68    1.04    1
24/10/2003  3.47    0.363   1
30/10/2003  2.42    0.507   1
02/05/2010  2.72    0.47    2
05/05/2010  2.6 0.  646     2
08/05/2010  2.67    0.205   2
11/05/2010  3.57    0.524   2
12/05/2010  0.428   4.68    3
13/05/2010  1.04    3.47    3
14/05/2010  0.363   2.42    3
18/10/2003  0.507   2.52    3
24/10/2003  0.418   4.68    3
30/10/2003  0.47    3.47    3
29/04/2010  0.646   2.42    4
18/10/2003  3.47    2.52    4

我将列ID的每组行数计为整数向量,如5 4 6 2

有没有办法用这些整数向量5 4 6 2

替换列id中的组值

我期待的输出是

DATE    x   y   ID
06/10/2003  7.21    0.651   5
12/10/2003  5.99    0.428   5
18/10/2003  4.68    1.04    5
24/10/2003  3.47    0.363   5
30/10/2003  2.42    0.507   5
02/05/2010  2.72    0.47    4
05/05/2010  2.6      646    4
08/05/2010  2.67    0.205   4
11/05/2010  3.57    0.524   4
12/05/2010  0.428   4.68    6
13/05/2010  1.04    3.47    6
14/05/2010  0.363   2.42    6
18/10/2003  0.507   2.52    6
24/10/2003  0.418   4.68    6
30/10/2003  0.47    3.47    6
29/04/2010  0.646   2.42    2
18/10/2003  3.47    2.52    2

我对R很新,并试图找出是否有任何想法替换功能。但是很难过。任何帮助深表感谢。

以上数据只是了解我的要求的一个例子。

3 个答案:

答案 0 :(得分:2)

您可以使用ave()函数计算每个ID占用的行数。在下面的示例中,我创建了一个新变量ID2,但您可以根据需要替换原始ID。

(我在下面列出了用于在R中创建数据的代码,但是当您将来提出问题时,请使用数据对象上的dput()函数在问题中包含您的数据。这就是我要做的下面的代码。)

mydata <- structure(list(DATE = c("06/10/2003", "12/10/2003", "18/10/2003", 
                        "24/10/2003", "30/10/2003", "02/05/2010", "05/05/2010", "08/05/2010", 
                        "11/05/2010", "12/05/2010", "13/05/2010", "14/05/2010", "18/10/2003", 
                        "24/10/2003", "30/10/2003", "29/04/2010", "18/10/2003"), 
                   x = c(7.21, 5.99, 4.68, 3.47, 2.42, 2.72, 2.6, 2.67, 3.57, 0.428, 1.04, 0.363, 
                         0.507, 0.418, 0.47, 0.646, 3.47), 
                   y = c(0.651, 0.428, 1.04, 0.363, 0.507, 0.47, 646, 0.205, 0.524, 4.68, 3.47, 
                         2.42, 2.52, 4.68, 3.47, 2.42, 2.52), 
             ID = c(1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 4, 4)), 
             .Names = c("DATE", "x", "y", "ID"), 
             class = c("data.frame"), 
             row.names = c(NA, -17L))

# ave() takes an input object, an object of group IDs of the same length 
#   as the input object, and a function to apply to the input object split across groups         
mydata$ID2 <- ave(mydata$ID, mydata$ID, FUN = length)

mydata

   DATE       x       y     ID ID2
1  06/10/2003 7.210   0.651  1   5
2  12/10/2003 5.990   0.428  1   5
3  18/10/2003 4.680   1.040  1   5
4  24/10/2003 3.470   0.363  1   5
5  30/10/2003 2.420   0.507  1   5
6  02/05/2010 2.720   0.470  2   4
7  05/05/2010 2.600 646.000  2   4
8  08/05/2010 2.670   0.205  2   4
9  11/05/2010 3.570   0.524  2   4
10 12/05/2010 0.428   4.680  3   6
11 13/05/2010 1.040   3.470  3   6
12 14/05/2010 0.363   2.420  3   6
13 18/10/2003 0.507   2.520  3   6
14 24/10/2003 0.418   4.680  3   6
15 30/10/2003 0.470   3.470  3   6
16 29/04/2010 0.646   2.420  4   2
17 18/10/2003 3.470   2.520  4   2

# if you want to replace the original ID variable, you can assign to it 
#   instead of adding a new variable
mydata$ID <- ave(mydata$ID, mydata$ID, FUN = length)

答案 1 :(得分:2)

使用data.table - 包的紧凑型解决方案:

library(data.table)
setDT(mydf)[, ID := .N, by = ID][]

给出:

> mydf
          DATE     x     y ID
 1: 06/10/2003 7.210 0.651  5
 2: 12/10/2003 5.990 0.428  5
 3: 18/10/2003 4.680 1.040  5
 4: 24/10/2003 3.470 0.363  5
 5: 30/10/2003 2.420 0.507  5
 6: 02/05/2010 2.720 0.470  4
 7: 05/05/2010 2.600 0.646  4
 8: 08/05/2010 2.670 0.205  4
 9: 11/05/2010 3.570 0.524  4
10: 12/05/2010 0.428 4.680  6
11: 13/05/2010 1.040 3.470  6
12: 14/05/2010 0.363 2.420  6
13: 18/10/2003 0.507 2.520  6
14: 24/10/2003 0.418 4.680  6
15: 30/10/2003 0.470 3.470  6
16: 29/04/2010 0.646 2.420  2
17: 18/10/2003 3.470 2.520  2

这是做什么的:

  • setDT(mydf)将数据框转换为 data.table
  • by = ID分组ID
  • ID := .NID的原始值替换为按组计算

答案 2 :(得分:1)

dplyr的解决方案:

library(dplyr)
df %>%
  group_by(ID) %>%
  mutate(ID2 = n()) %>%
  ungroup() %>%
  mutate(ID = ID2) %>%
  select(-ID2)

修改

我刚刚找到了一个比上述更清洁的解决方案:

df %>%
  group_by(ID2 = ID) %>%
  mutate(ID = n()) %>%
  select(-ID2)

<强>结果:

# A tibble: 17 x 4
         DATE     x     y    ID
       <fctr> <dbl> <dbl> <int>
 1 06/10/2003 7.210 0.651     5
 2 12/10/2003 5.990 0.428     5
 3 18/10/2003 4.680 1.040     5
 4 24/10/2003 3.470 0.363     5
 5 30/10/2003 2.420 0.507     5
 6 02/05/2010 2.720 0.470     4
 7 05/05/2010 2.600 0.646     4
 8 08/05/2010 2.670 0.205     4
 9 11/05/2010 3.570 0.524     4
10 12/05/2010 0.428 4.680     6
11 13/05/2010 1.040 3.470     6
12 14/05/2010 0.363 2.420     6
13 18/10/2003 0.507 2.520     6
14 24/10/2003 0.418 4.680     6
15 30/10/2003 0.470 3.470     6
16 29/04/2010 0.646 2.420     2
17 18/10/2003 3.470 2.520     2

备注:

ungroup() %>% mutate(ID = ID2) %>% select(-ID2)背后的原因是dplyr不允许mutate分组变量。所以这不起作用:

df %>%
   group_by(ID) %>%
   mutate(ID = n())
  

mutate_impl(.data,dots)出错:列ID无法修改   因为它是一个分组变量

如果您不关心替换原始ID列,您可以这样做:

df %>%
  group_by(ID) %>%
  mutate(ID2 = n())

替代结果:

# A tibble: 17 x 5
# Groups:   ID [4]
         DATE     x     y    ID   ID2
       <fctr> <dbl> <dbl> <int> <int>
 1 06/10/2003 7.210 0.651     1     5
 2 12/10/2003 5.990 0.428     1     5
 3 18/10/2003 4.680 1.040     1     5
 4 24/10/2003 3.470 0.363     1     5
 5 30/10/2003 2.420 0.507     1     5
 6 02/05/2010 2.720 0.470     2     4
 7 05/05/2010 2.600 0.646     2     4
 8 08/05/2010 2.670 0.205     2     4
 9 11/05/2010 3.570 0.524     2     4
10 12/05/2010 0.428 4.680     3     6
11 13/05/2010 1.040 3.470     3     6
12 14/05/2010 0.363 2.420     3     6
13 18/10/2003 0.507 2.520     3     6
14 24/10/2003 0.418 4.680     3     6
15 30/10/2003 0.470 3.470     3     6
16 29/04/2010 0.646 2.420     4     2
17 18/10/2003 3.470 2.520     4     2