R: rbind 一个 data.frames 的列表,在不同的数据框中有不同的列
R: rbind a list of data.frames with different columns in different data frames
我有一个包含 11,383 个数据帧的列表。我需要将它们合并到一个大数据框中,但是它们有不同的列(2、3、4 列),所以当我使用 Dplyr 中的 rbind_all 时,我得到的结果不是我想要的。
一种解决方法是绑定具有相同列数的数据帧(它们具有不同的 headers,但我不介意它们)。由于我有 2,3 和 4 列的数据框,根据列表中每个数据框的列数,它会产生 3 个大数据框。
预期输出:
具有 4 列的数据框:
SKU Tv y Video Tecnología Deportes
2003091070002P Tv y Video Tecnología Deportes
2.00E+12 Tv y Video Tecnología Deportes
2003120060008P Tv y Video Tecnología Deportes
2004121460080P Cómputo Tecnología Decohogar
2.00G+12 Cómputo Tecnología Decohogar
2004121440802P Cómputo Tecnología Decohogar
2.00A+12 Cómputo Tecnología Decohogar
具有 2 列的数据框:
SKU PROMOCIONES
1 110 2089060010006P PROMOCIONES
2 111 2089660010006P PROMOCIONES
#
这是我的代码:
df_2col <- data.frame() #Starts Data frame for dfs with 2 columns
df_3col <- data.frame() #Starts Data frame for dfs with 3 columns
df_4col <- data.frame() #Starts Data frame for dfs with 4 columns
lapply(my_list, function(i){
if (ncol(i) == 2)
df_2col <- rbind(i)
ifelse (ncol(i) == 3)
df_3col <- rbind(i)
ifelse (ncol(i) == 4)
df_4col <- rbind(i)
})
但是我得到这个错误:
Error in ifelse(ncol(i) == 3) : argument "no" is missing, with no default
我的数据列表示例:
list(list(structure(list(SKU = "2079230130006P", Decohogar = "Decohogar",
Para.la.Mesa = "Para.la.Mesa", Copas.y.Vasos = "Copas.y.Vasos"), .Names = c("SKU",
"Decohogar", "Para.la.Mesa", "Copas.y.Vasos"), class = "data.frame", row.names = 134L)),
list(structure(list(SKU = "2079240080001P", Decohogar = "Decohogar",
Para.la.Mesa = "Para.la.Mesa", Copas.y.Vasos = "Copas.y.Vasos"), .Names = c("SKU",
"Decohogar", "Para.la.Mesa", "Copas.y.Vasos"), class = "data.frame", row.names = 132L)),
list(structure(list(SKU = "2069060020005P", PROMOCIONES = "PROMOCIONES"), .Names = c("SKU",
"PROMOCIONES"), class = "data.frame", row.names = 111L)),
list(structure(list(SKU = "2047121452095P", Dormitorio = "Dormitorio",
Colchones = "Colchones", X2.plazas = "X2.plazas"), .Names = c("SKU",
"Dormitorio", "Colchones", "X2.plazas"), class = "data.frame", row.names = 223L)),
list(structure(list(SKU = "2069060010006P", PROMOCIONES = "PROMOCIONES"), .Names = c("SKU",
"PROMOCIONES"), class = "data.frame", row.names = 110L)),
list(structure(list(SKU = "2069060010006P", PROMOCIONES = "PROMOCIONES"), .Names = c("SKU",
"PROMOCIONES"), class = "data.frame", row.names = 109L)))
注意:当您知道列表中每个数据框的列数时,这将起作用。有没有办法做到这一点?我的意思是,如果将来有一个包含 5 列的数据框,代码应该 return 也为这个数据框提供一个包含 5 列的大数据框。
我们可以展平列表元素 do.call(
c,..)
获取每个列表元素 ("indx") 的列数 (ncol
),用它来 split
列表,rbindlist
结果元素。
library(data.table)
my_list1 <- do.call(`c`, my_list)
indx <- sapply(my_list1, ncol)
lst <- lapply(split(my_list1, indx), rbindlist)
lst
#$`2`
# SKU PROMOCIONES
#1: 2069060020005P PROMOCIONES
#2: 2069060010006P PROMOCIONES
#3: 2069060010006P PROMOCIONES
#$`4`
# SKU Decohogar Para.la.Mesa Copas.y.Vasos
#1: 2089230130006P Decohogar Para.la.Mesa Copas.y.Vasos
#2: 2089240080001P Decohogar Para.la.Mesa Copas.y.Vasos
#3: 2047121452095P Dormitorio Colchones X2.plazas
如果我们需要获取单独的data.frame
对象(不推荐),使用list2env
list2env(setNames(lst, paste0('dat',seq_along(lst))), envir=.GlobalEnv)
更新
如果有 NULL 或 NA 值作为列表元素之一,我们可能会收到此错误
my_list1[[7]] <- NA
split(my_list1, sapply(my_list1, ncol))
#Error in split.default(my_list1, sapply(my_list1, ncol)) :
#group length is 0 but data length > 0
然后,我们可以检查元素是否为data.frame
("isDF"),将列表子集化并得到"ncol",和以前一样。
isDF <- sapply(my_list1, is.data.frame)
indx <- sapply(my_list1[isDF], ncol)
lapply(split(my_list1[isDF], indx), rbindlist)
rbind_all有一个填充函数,用NA替换空白数据。
当我第一次尝试使用 rbind 时出现错误,因为您提供的数据集是列表列表而不是数据帧列表。我首先将嵌套列表转换为数据帧,然后使用 rbind 创建单个数据帧。
您的示例数据是 "x"
sapply(x, class)
x2 <- lapply(x, as.data.frame)
x3 <- rbind_all(x2)
我不知道你是否正在制作一个整洁的数据框,但如果你是,你可以使用 tidyr 来帮助
library(tidyr)
x4 <- gather(x3, key=SKU, na.rm=TRUE)[,-2]
更新
问题现在已解决,但这是我对解决方案的更新,列出了各个类别的数据帧
x5 <- lapply(unique(x4$value), function(n) filter(x4, value == n))
我有一个包含 11,383 个数据帧的列表。我需要将它们合并到一个大数据框中,但是它们有不同的列(2、3、4 列),所以当我使用 Dplyr 中的 rbind_all 时,我得到的结果不是我想要的。
一种解决方法是绑定具有相同列数的数据帧(它们具有不同的 headers,但我不介意它们)。由于我有 2,3 和 4 列的数据框,根据列表中每个数据框的列数,它会产生 3 个大数据框。
预期输出:
具有 4 列的数据框:
SKU Tv y Video Tecnología Deportes
2003091070002P Tv y Video Tecnología Deportes
2.00E+12 Tv y Video Tecnología Deportes
2003120060008P Tv y Video Tecnología Deportes
2004121460080P Cómputo Tecnología Decohogar
2.00G+12 Cómputo Tecnología Decohogar
2004121440802P Cómputo Tecnología Decohogar
2.00A+12 Cómputo Tecnología Decohogar
具有 2 列的数据框:
SKU PROMOCIONES
1 110 2089060010006P PROMOCIONES
2 111 2089660010006P PROMOCIONES
#
这是我的代码:
df_2col <- data.frame() #Starts Data frame for dfs with 2 columns
df_3col <- data.frame() #Starts Data frame for dfs with 3 columns
df_4col <- data.frame() #Starts Data frame for dfs with 4 columns
lapply(my_list, function(i){
if (ncol(i) == 2)
df_2col <- rbind(i)
ifelse (ncol(i) == 3)
df_3col <- rbind(i)
ifelse (ncol(i) == 4)
df_4col <- rbind(i)
})
但是我得到这个错误:
Error in ifelse(ncol(i) == 3) : argument "no" is missing, with no default
我的数据列表示例:
list(list(structure(list(SKU = "2079230130006P", Decohogar = "Decohogar",
Para.la.Mesa = "Para.la.Mesa", Copas.y.Vasos = "Copas.y.Vasos"), .Names = c("SKU",
"Decohogar", "Para.la.Mesa", "Copas.y.Vasos"), class = "data.frame", row.names = 134L)),
list(structure(list(SKU = "2079240080001P", Decohogar = "Decohogar",
Para.la.Mesa = "Para.la.Mesa", Copas.y.Vasos = "Copas.y.Vasos"), .Names = c("SKU",
"Decohogar", "Para.la.Mesa", "Copas.y.Vasos"), class = "data.frame", row.names = 132L)),
list(structure(list(SKU = "2069060020005P", PROMOCIONES = "PROMOCIONES"), .Names = c("SKU",
"PROMOCIONES"), class = "data.frame", row.names = 111L)),
list(structure(list(SKU = "2047121452095P", Dormitorio = "Dormitorio",
Colchones = "Colchones", X2.plazas = "X2.plazas"), .Names = c("SKU",
"Dormitorio", "Colchones", "X2.plazas"), class = "data.frame", row.names = 223L)),
list(structure(list(SKU = "2069060010006P", PROMOCIONES = "PROMOCIONES"), .Names = c("SKU",
"PROMOCIONES"), class = "data.frame", row.names = 110L)),
list(structure(list(SKU = "2069060010006P", PROMOCIONES = "PROMOCIONES"), .Names = c("SKU",
"PROMOCIONES"), class = "data.frame", row.names = 109L)))
注意:当您知道列表中每个数据框的列数时,这将起作用。有没有办法做到这一点?我的意思是,如果将来有一个包含 5 列的数据框,代码应该 return 也为这个数据框提供一个包含 5 列的大数据框。
我们可以展平列表元素 do.call(
c,..)
获取每个列表元素 ("indx") 的列数 (ncol
),用它来 split
列表,rbindlist
结果元素。
library(data.table)
my_list1 <- do.call(`c`, my_list)
indx <- sapply(my_list1, ncol)
lst <- lapply(split(my_list1, indx), rbindlist)
lst
#$`2`
# SKU PROMOCIONES
#1: 2069060020005P PROMOCIONES
#2: 2069060010006P PROMOCIONES
#3: 2069060010006P PROMOCIONES
#$`4`
# SKU Decohogar Para.la.Mesa Copas.y.Vasos
#1: 2089230130006P Decohogar Para.la.Mesa Copas.y.Vasos
#2: 2089240080001P Decohogar Para.la.Mesa Copas.y.Vasos
#3: 2047121452095P Dormitorio Colchones X2.plazas
如果我们需要获取单独的data.frame
对象(不推荐),使用list2env
list2env(setNames(lst, paste0('dat',seq_along(lst))), envir=.GlobalEnv)
更新
如果有 NULL 或 NA 值作为列表元素之一,我们可能会收到此错误
my_list1[[7]] <- NA
split(my_list1, sapply(my_list1, ncol))
#Error in split.default(my_list1, sapply(my_list1, ncol)) :
#group length is 0 but data length > 0
然后,我们可以检查元素是否为data.frame
("isDF"),将列表子集化并得到"ncol",和以前一样。
isDF <- sapply(my_list1, is.data.frame)
indx <- sapply(my_list1[isDF], ncol)
lapply(split(my_list1[isDF], indx), rbindlist)
rbind_all有一个填充函数,用NA替换空白数据。 当我第一次尝试使用 rbind 时出现错误,因为您提供的数据集是列表列表而不是数据帧列表。我首先将嵌套列表转换为数据帧,然后使用 rbind 创建单个数据帧。
您的示例数据是 "x"
sapply(x, class)
x2 <- lapply(x, as.data.frame)
x3 <- rbind_all(x2)
我不知道你是否正在制作一个整洁的数据框,但如果你是,你可以使用 tidyr 来帮助
library(tidyr)
x4 <- gather(x3, key=SKU, na.rm=TRUE)[,-2]
更新
问题现在已解决,但这是我对解决方案的更新,列出了各个类别的数据帧
x5 <- lapply(unique(x4$value), function(n) filter(x4, value == n))