为大型数据库中的每个标识符添加一行由 0 组成的行
Add a row made of 0 for each identifier in a large database
我有一个数据库,其中缺少每个唯一标识符的第一行。
基本上,我需要为每个唯一 ID 添加一个由 0 组成的新行。
我的数据库看起来是这样的(我有超过一百万行,所以循环基本上是不可能的)。
dt = as.data.frame( rbind(c('A1', '15', '1'),
c('A1', '17', '2'),
c('A1', '12', '3'),
c('B1', '3', '1'),
c('B1', '4', '2'),
c('B1', '15', '3')))
colnames(dt) = c('id', 'activity', 'time')
对于每个 id,我需要在时间 0 添加一个 0 行。
以下代码行有效,但是,我的数据库需要太多时间。
IdUnique = length(unique(dt$id))
VeK = vector('list', IdUnique)
for(i in 1:IdUnique){
row0 = matrix(0, nrow = 1, ncol = ncol(dt), dimnames = list(unique(dt$id)[i], colnames(dt)))
VeK[[i]] = rbind(row0, subset(dt, id == unique(dt$id)[i]) )
VeK[[i]][,'id'] <- unique(dt$id)[i]
}
dt2 <- do.call("rbind", VeK)
我想知道是否有更经济的解决方案,比如按行合并
并通过身份证。但我不知道该怎么做。
mat = matrix(0, nrow = length(unique(dt$id)), ncol = ncol (dt) )
colnames(mat) <- colnames(dt)
mat[, 'id'] <- as.character(unique(dt$id))
mat <- as.data.frame(mat)
merge(mat, dt, by = 'id' )
任何按行合并和控制标识符的解决方案?
尝试:
library(dplyr)
dt %>%
group_by(id) %>%
summarise(activity = 0, time = 0) %>%
merge(., dt, all = T) %>%
arrange(id, time)
或:
dt %>%
group_by(id) %>%
summarise_each(funs(as.character(0))) %>%
full_join(., dt) %>%
arrange(id, time)
给出:
# id activity time
#1 A1 0 0
#2 A1 15 1
#3 A1 17 2
#4 A1 12 3
#5 B1 0 0
#6 B1 3 1
#7 B1 4 2
#8 B1 15 3
之后,如果您想将 activity
和 time
列转换为数字,您可以添加:
... %>% mutate_each(funs(type.convert(as.character(.))), -id)
更新
如果 class 差异不是您原来 dt
中有意造成的,它会更容易一些:
dt <- data.frame(id = c(rep("A1", 3), rep("B1", 3)),
activity = c(15,17,12,3,4,15),
time = rep(1:3, 2))
library(dplyr)
dt %>%
group_by(id) %>%
summarise(activity = 0, time = 0) %>%
full_join(., dt) %>%
arrange(id, time)
首先,我猜你必须以 activity
和 time
都是 class int
而不是 dt
的方式转换你的 dt
factor
:
dt[]<-lapply(dt,function(x) type.convert(as.character(x)))
然后,您可以使用 data.table
:
require(data.table)
DT<-as.data.table(dt)
DT[,lapply(.SD,function(x) c(0,x)),by=id]
dt = as.data.frame( rbind(c('A1', '15', '1'),
c('A1', '17', '2'),
c('A1', '12', '3'),
c('B1', '3', '1'),
c('B1', '4', '2'),
c('B1', '15', '3')
))
colnames(dt) = c('id', 'activity', 'time')
#Just we need to get the levels of `id` we want to bind `zeros` to
levels <- levels(dt$id)
#create a new matrix of new data we need to append to our data frame `dt`
levels_M <- cbind(id = levels , activity = '0' , time = '0')
#then simply bind these values to the data frame
rbind(dt , levels_M)
#if you want to order the final results
dt <- dt[order(dt$id),]
订购也可以使用data.table
库,当然它会比base R
订购
快
我有一个数据库,其中缺少每个唯一标识符的第一行。 基本上,我需要为每个唯一 ID 添加一个由 0 组成的新行。
我的数据库看起来是这样的(我有超过一百万行,所以循环基本上是不可能的)。
dt = as.data.frame( rbind(c('A1', '15', '1'),
c('A1', '17', '2'),
c('A1', '12', '3'),
c('B1', '3', '1'),
c('B1', '4', '2'),
c('B1', '15', '3')))
colnames(dt) = c('id', 'activity', 'time')
对于每个 id,我需要在时间 0 添加一个 0 行。
以下代码行有效,但是,我的数据库需要太多时间。
IdUnique = length(unique(dt$id))
VeK = vector('list', IdUnique)
for(i in 1:IdUnique){
row0 = matrix(0, nrow = 1, ncol = ncol(dt), dimnames = list(unique(dt$id)[i], colnames(dt)))
VeK[[i]] = rbind(row0, subset(dt, id == unique(dt$id)[i]) )
VeK[[i]][,'id'] <- unique(dt$id)[i]
}
dt2 <- do.call("rbind", VeK)
我想知道是否有更经济的解决方案,比如按行合并 并通过身份证。但我不知道该怎么做。
mat = matrix(0, nrow = length(unique(dt$id)), ncol = ncol (dt) )
colnames(mat) <- colnames(dt)
mat[, 'id'] <- as.character(unique(dt$id))
mat <- as.data.frame(mat)
merge(mat, dt, by = 'id' )
任何按行合并和控制标识符的解决方案?
尝试:
library(dplyr)
dt %>%
group_by(id) %>%
summarise(activity = 0, time = 0) %>%
merge(., dt, all = T) %>%
arrange(id, time)
或:
dt %>%
group_by(id) %>%
summarise_each(funs(as.character(0))) %>%
full_join(., dt) %>%
arrange(id, time)
给出:
# id activity time
#1 A1 0 0
#2 A1 15 1
#3 A1 17 2
#4 A1 12 3
#5 B1 0 0
#6 B1 3 1
#7 B1 4 2
#8 B1 15 3
之后,如果您想将 activity
和 time
列转换为数字,您可以添加:
... %>% mutate_each(funs(type.convert(as.character(.))), -id)
更新
如果 class 差异不是您原来 dt
中有意造成的,它会更容易一些:
dt <- data.frame(id = c(rep("A1", 3), rep("B1", 3)),
activity = c(15,17,12,3,4,15),
time = rep(1:3, 2))
library(dplyr)
dt %>%
group_by(id) %>%
summarise(activity = 0, time = 0) %>%
full_join(., dt) %>%
arrange(id, time)
首先,我猜你必须以 activity
和 time
都是 class int
而不是 dt
的方式转换你的 dt
factor
:
dt[]<-lapply(dt,function(x) type.convert(as.character(x)))
然后,您可以使用 data.table
:
require(data.table)
DT<-as.data.table(dt)
DT[,lapply(.SD,function(x) c(0,x)),by=id]
dt = as.data.frame( rbind(c('A1', '15', '1'),
c('A1', '17', '2'),
c('A1', '12', '3'),
c('B1', '3', '1'),
c('B1', '4', '2'),
c('B1', '15', '3')
))
colnames(dt) = c('id', 'activity', 'time')
#Just we need to get the levels of `id` we want to bind `zeros` to
levels <- levels(dt$id)
#create a new matrix of new data we need to append to our data frame `dt`
levels_M <- cbind(id = levels , activity = '0' , time = '0')
#then simply bind these values to the data frame
rbind(dt , levels_M)
#if you want to order the final results
dt <- dt[order(dt$id),]
订购也可以使用data.table
库,当然它会比base R
订购