根据特定行值向数据框添加列(2)

时间:2016-08-09 09:59:44

标签: r dataframe add

我必须调整一个代码,该代码与不同的data.frame完美配合,但具有相似的条件。

这是我的data.frame的一个例子:

df <- read.table(text = 'ID    Day Count
    33012   9526    4
    35004   9526    4
    37006   9526    4
    37008   9526    4
    21009   1913    3
    24005   1913    3
    25009   1913    3
    22317   2286    2
    37612   2286    2
    25009   14329   1
    48007   9527    0
    88662   9528    0
    1845    9528    0
    8872    2287    0
    49002   1914    0
    1664    1915    0', header = TRUE)

我需要在我的data.frame中添加一个新列(new_col),其中包含1到4的值。这些new_col值必须包含每一天,每天(x)天( x +1)和day(x +2),其中x = 9526,1913,2286,14329(列Day)。

我的输出应该如下:

   ID    Day Count  new_col
33012   9526    4     1
35004   9526    4     1
37006   9526    4     1
37008   9526    4     1
21009   1913    3     2
24005   1913    3     2
25009   1913    3     2
22317   2286    2     3
37612   2286    2     3
25009   14329   1     4
48007   9527    0     1
88662   9528    0     1
1845    9528    0     1
8872    2287    0     3
49002   1914    0     2
1664    1915    0     2

new_col订购的data.frame将是:

   ID    Day Count  new_col
33012   9526    4     1
35004   9526    4     1
37006   9526    4     1
37008   9526    4     1
48007   9527    0     1
88662   9528    0     1
1845    9528    0     1
21009   1913    3     2
24005   1913    3     2
25009   1913    3     2
49002   1914    0     2
1664    1915    0     2
22317   2286    2     3
37612   2286    2     3
8872    2287    0     3
25009   14329   1     4

我的真实数据框架比示例更复杂(即Count列中有更多列和更多值。)

@mrbrick在上一个问题(Add column to dataframe depending on specific row values)中建议我的代码如下:

x <- c(1913, 2286, 9526, 14329) 
df$new_col <- cut(df$Day, c(-Inf, x, Inf))
df$new_col <- as.numeric(factor(df$new_col, levels=unique(df$new_col)))

但它仅适用于第x天,第x天和第x天。

任何建议都会非常有用。

2 个答案:

答案 0 :(得分:1)

假设不同连续组中的Day值使得删除Day的最后两位数字表示每个组将剩余的数据转换为具有序列号作为标签的因子。没有包使用。

 g <- df$Day %/% 100
 u <- unique(g)
 transform(df, new_col = factor(g, levels = u, labels = seq_along(u)))

,并提供:

      ID   Day Count new_col
1  33012  9526     4       1
2  35004  9526     4       1
3  37006  9526     4       1
4  37008  9526     4       1
5  21009  1913     3       2
6  24005  1913     3       2
7  25009  1913     3       2
8  22317  2286     2       3
9  37612  2286     2       3
10 25009 14329     1       4
11 48007  9527     0       1
12 88662  9528     0       1
13  1845  9528     0       1
14  8872  2287     0       3
15 49002  1914     0       2
16  1664  1915     0       2

另一种可能性是用以下之一替换g <- ...行:

(a)已知数量的群组使用kmeans以及适当数量的群集:

g <- kmeans(df$Day, 4)$cluster

(b)手动设置或手动设置中心并使用它来启动kmeans

centers <-  c(1913, 2286, 9526, 14329) + 1
g <- kmeans(df$day, centers)$cluster

(c)检查x-1和x-2 或像这样派生centers。如果某一天x没有x-1x-2,则x必须是序列中的第一个,因此我们选择此类值并添加1以获取中心。与(a)要求我们知道簇的数量和(b)要求我们知道实际序列不同,这不需要知道它们。

centers <- with(df, unique(Day[ ! ((Day-1) %in% Day) & ! ((Day-2) %in% Day) ]) + 1)
g <- kmeans(df$Day, centers)$cluster

(d)简化最后一点或者如果我们保证如果x是序列中的第一个,那么x,x + 1和x + 2都会出现,那么我们就可以了如果没有x,请确保x-1是序列中的第一个,因此我们可以简化(c):

# assumes x, x+1, x+2 all appear for each sequence
centers <- with(df, unique(Day[ ! (Day-1) %in% Day ]) + 1)
g <- kmeans(df$Day, centers)$cluster

kmeans解决方案应该可以正常工作,如果这些组是充分分离的,并且基于问题中显示的数据,它们似乎是。

答案 1 :(得分:0)

使用基础R,您可以创建一个包含ID列的数据框,您想要的日期(xx+1x+2)以及new_col您想要,然后将此data.frame与原始数据合并。

如果您事先知道所有x天的日期,那么该方法很有效。

df <- read.table(text = 'ID    Day Count
    33012   9526    4
                 35004   9526    4
                 37006   9526    4
                 37008   9526    4
                 21009   1913    3
                 24005   1913    3
                 25009   1913    3
                 22317   2286    2
                 37612   2286    2
                 25009   14329   1
                 48007   9527    0
                 88662   9528    0
                 1845    9528    0
                 8872    2287    0
                 49002   1914    0
                 1664    1915    0', header = TRUE)
# identify the day you want (x variable in your example)
x <- c(9526, 1913, 2286, 14329)
# create new_col for each x as you wish, and repeat for x + i, then rbind the results data.frame
new_col_df <- do.call(rbind, 
                      lapply(seq(0, 2, by = 1), 
                             function(add) data.frame(x = x + add, new_col = seq_along(x))
                             )
                      )
# merge with the original df
output_df <-merge(df, new_col_df, by.x = "Day", by.y = "x")
# ordered output is
output_df[order(output_df$new_col),]
#>      Day    ID Count new_col
#> 9   9526 33012     4       1
#> 10  9526 35004     4       1
#> 11  9526 37006     4       1
#> 12  9526 37008     4       1
#> 13  9527 48007     0       1
#> 14  9528 88662     0       1
#> 15  9528  1845     0       1
#> 1   1913 21009     3       2
#> 2   1913 24005     3       2
#> 3   1913 25009     3       2
#> 4   1914 49002     0       2
#> 5   1915  1664     0       2
#> 6   2286 22317     2       3
#> 7   2286 37612     2       3
#> 8   2287  8872     0       3
#> 16 14329 25009     1       4