创建两个新列并删除源列

时间:2019-12-08 00:39:44

标签: r dataframe

我有以下示例数据:

df <- data.frame(ID=c("A1","A2","A3","A4","A1","A2","A3","A4"),
                 NUM=c(469,586,394,595,398,203,604,809))

我正在寻找提取NUM列的第一个值并将其放置在新列NUM1中,然后在第二次出现具有相同ID的NUM值时,将该值提取到新列NUM2中。最后,我想删除原始列。除了ID和NUM,我拥有的数据集还有许多其他变量和列。以下是所需的输出。

df1 <- data.frame(ID=c("A1","A2","A3","A4"),NUM1=c(469,586,394,595),NUM2=c(398,203,604,809))

6 个答案:

答案 0 :(得分:2)

这是一种方法。您将需要创建一个COL列作为新列的名称,因此在这种情况下,我们使用group_bystr_c来创建此列。 pivot_widerspread函数的更新版本。所有这些功能均来自tidyverse软件包。

library(tidyverse)

df1 <- df %>%
  group_by(ID) %>%
  mutate(COL = str_c("NUM", row_number())) %>%
  pivot_wider(names_from = COL, values_from = NUM) %>%
  ungroup()
df1
# # A tibble: 4 x 3
#   ID     NUM1  NUM2
#   <fct> <dbl> <dbl>
# 1 A1      469   398
# 2 A2      586   203
# 3 A3      394   604
# 4 A4      595   809

答案 1 :(得分:1)

使用基数R您可以:

 reshape(transform(df,time=cumsum(grepl("1",ID))),idvar = "ID",dir="wide",sep="")

  ID NUM1 NUM2
1 A1  469  398
2 A2  586  203
3 A3  394  604
4 A4  595  809

或者您可以尝试:

`colnames<-`(t(unstack(df,NUM~ID)),c("NUM1","NUM2"))
   NUM1 NUM2
A1  469  398
A2  586  203
A3  394  604
A4  595  809

答案 2 :(得分:1)

@akrun雄辩的Base R解决方案:

df1 <- aggregate(NUM ~ ID, df, I)

(我的)Base R解决方案:

#Transform the dataframe: 

df1 <- within(df, {
              count_num_by_id <- ave(NUM, ID, FUN = seq.int);
              NUM2 <- ifelse(count_num_by_id == 2, NUM, 0);
              NUM <- ifelse(count_num_by_id == 1, NUM, 0);
              rm(count_num_by_id)})

# Aggregate the dataframe: 

df1 <- data.frame(aggregate(.~ID, df1, sum))

答案 3 :(得分:0)

您可以通过子设置获取每个ID的第一个和第二个值

library(dplyr)

df %>%
  group_by(ID) %>%
  summarise(NUM1 = NUM[1L], 
            NUM2 = NUM[2L])

# A tibble: 4 x 3
#  ID     NUM1  NUM2
#  <fct> <dbl> <dbl>
#1 A1      469   398
#2 A2      586   203
#3 A3      394   604
#4 A4      595   809

如果您要维护其他列,则可以使用mutate

library(dplyr)
df %>%
  group_by(ID) %>%
  mutate(NUM1 = NUM[1L], 
         NUM2 = NUM[2L]) %>%
  slice(1L) %>%
  select(-NUM)

答案 4 :(得分:0)

data.table解决方案...

require(data.table)

# Set as a data.table and create a unique row.
setDT(df)[, rid := paste0('NUM', rowid(ID))]

# Cast the data by ID and rid.
df <- dcast(df, ID ~ rid, value.var = 'NUM')

df
#    ID NUM1 NUM2
# 1: A1  469  398
# 2: A2  586  203
# 3: A3  394  604
# 4: A4  595  809

答案 5 :(得分:0)

这是一种alternative dcast()方法,该方法直接在公式中调用rowid(),还将处理df中的其他列:

library(data.table)
dcast(setDT(df), ID + ... ~ rowid(ID, prefix = "NUM"), value.var = "NUM")
   ID NUM1 NUM2
1: A1  469  398
2: A2  586  203
3: A3  394  604
4: A4  595  809

请注意prefix = "NUM"的调用中的rowid()参数。

df中的其他列

OP指出,他的数据集[...]除了ID和NUM 还有更多的变量和列。

如果 ,每个ID的附加列的值都相同,那么+ ...会将它们添加到输出中:

df2 <- data.frame(
  ID = c("A1", "A2", "A3", "A4", "A1", "A2", "A3", "A4"),
  NUM = c(469, 586, 394, 595, 398, 203, 604, 809),
  other1 = rep(4:1, 2),
  other2 = rep(letters[1:4], 2)
)

df2
  ID NUM other1 other2
1 A1 469      4      a
2 A2 586      3      b
3 A3 394      2      c
4 A4 595      1      d
5 A1 398      4      a
6 A2 203      3      b
7 A3 604      2      c
8 A4 809      1      d
dcast(setDT(df2), ID + ... ~ rowid(ID, prefix = "NUM"), value.var = "NUM")
   ID other1 other2 NUM1 NUM2
1: A1      4      a  469  398
2: A2      3      b  586  203
3: A3      2      c  394  604
4: A4      1      d  595  809