根据重复序列划分数据帧行

时间:2015-05-27 04:02:19

标签: r dataframe

我在下面有一个示例数据框。我试图获取3行的每个序列并将第一个除以第3个(或者换句话说,对于每个id,将类“a”除以类“c”)。最简单的方法是什么?提前致谢。

$count = intval(file_get_contents("p.txt"));
file_put_contents("p.txt",++$count);

2 个答案:

答案 0 :(得分:2)

您可以使用by ID 分组,然后使用进行分组:

by(data = data, INDICES = data$id, 
   FUN = function(ds) ds[ds$class == "a", "value"] / 
                      ds[ds$class == "c", "value"])

这将为每个 id 生成一个值。输出:

data$id: 0
[1] 0.6885714
----------------------------------------------------------------------------------------- 
data$id: 40
[1] 0.5989975
------------------------------------------------------------------------------------------ 
data$id: 53
[1] 0.6196078
------------------------------------------------------------------------------------------ 
data$id: 54
[1] 0.7539432

答案 1 :(得分:1)

我们可以尝试使用split中的unsplit / base R。通过“id”列split数据集获取“列表”输出,通过添加新列('value1)在lapplytransform data.frame列表元素的列表中循环')基于将'class'('a'和'c')对应的'value'和{id'列的unsplit分开。

 unsplit(lapply(split(df1, df1$id), function(x) 
      transform(x, value1= value[class=='a']/value[class=='c'])), df1$id)
 #   id class value    value1
 #1   0     a   241 0.6885714
 #2   0     b   109 0.6885714
 #3   0     c   350 0.6885714
 #4  40     a   239 0.5989975
 #5  40     b   160 0.5989975
 #6  40     c   399 0.5989975
 #7  53     a   158 0.6196078
 #8  53     b    97 0.6196078
 #9  53     c   255 0.6196078
 #10 54     a   239 0.7539432
 #11 54     b    78 0.7539432
 #12 54     c   317 0.7539432

或者使用mutate中的dplyr在按“ID”列分组后创建新列

library(dplyr)
df1 %>% 
     group_by(id) %>% 
      mutate(value1= value[class=='a']/value[class=='c'])
#    id class value    value1
#1   0     a   241 0.6885714
#2   0     b   109 0.6885714
#3   0     c   350 0.6885714
#4  40     a   239 0.5989975
#5  40     b   160 0.5989975
#6  40     c   399 0.5989975
#7  53     a   158 0.6196078
#8  53     b    97 0.6196078
#9  53     c   255 0.6196078
#10 54     a   239 0.7539432
#11 54     b    78 0.7539432
#12 54     c   317 0.7539432

或者如果它基于位置,即第一个和最后一个,您可以通过

更改上面代码中的最后一行
      mutate(value1=first(value)/last(value))

或者紧凑的方法是使用data.table:=运算符在创建'value1'列时速度非常快。将“data.frame”更改为“data.table”(setDT(df1)),创建按“id”分组的“value1”列。在这里,我选择了'值'的第一个(1L)和最后一个观察(.N),假设'a'和'c'是有序的。如果没有订购,请像以前一样使用value[class=='a']/value[class=='c']

library(data.table)
setDT(df1)[, value1:=value[1L]/value[.N] , id]
#   id class value    value1
#1:  0     a   241 0.6885714
#2:  0     b   109 0.6885714
#3:  0     c   350 0.6885714
#4: 40     a   239 0.5989975
#5: 40     b   160 0.5989975
#6: 40     c   399 0.5989975
#7: 53     a   158 0.6196078
#8: 53     b    97 0.6196078
#9: 53     c   255 0.6196078
#10:54     a   239 0.7539432
#11:54     b    78 0.7539432
#12:54     c   317 0.7539432

使用base R的另一种方法。虽然,这项工作在示例数据集上,但它可能不适用于未订购数据的情况。

df1$value1 <- (df1$value[df1$class=='a']/
        df1$value[df1$class=='c'])[as.numeric(factor(df1$id))]

更新

如果您需要为每个ID设置一个值,请将mutate替换为summarise中的dplyr

 df1 %>%
    group_by(id) %>% 
    summarise(value1= value[class=='a']/value[class=='c'])
 #   id    value1
 #1  0 0.6885714
 #2 40 0.5989975
 #3 53 0.6196078
 #4 54 0.7539432

或删除:=

中的分配(data.table
setDT(df1)[, list(value1=value[class=='a']/value[class=='c']), id]
 #    id    value1
 #1:  0 0.6885714
 #2: 40 0.5989975
 #3: 53 0.6196078
 #4: 54 0.7539432

数据

df1 <- structure(list(id = c(0L, 0L, 0L, 40L, 40L, 40L, 53L, 53L, 53L, 
54L, 54L, 54L), class = c("a", "b", "c", "a", "b", "c", "a", 
"b", "c", "a", "b", "c"), value = c(241L, 109L, 350L, 239L, 160L, 
399L, 158L, 97L, 255L, 239L, 78L, 317L)), .Names = c("id", "class", 
"value"), class = "data.frame", row.names = c(NA, -12L))