jac*_*tra 7 variables r list dataframe
伙计们,
我很难接受以下挑战.我有一个如下所示的数据集:
BuyerID Fruit.1 Fruit.2 Fruit.3 Amount.1 Amount.2 Amount.3
879 Banana Apple 4 3
765 Strawberry Apple Orange 1 2 4
123 Orange Banana 1 1 1
11 Strawberry 3
773 Kiwi Banana 1 2
Run Code Online (Sandbox Code Playgroud)
我想做的是简化数据(如果可能)并折叠"Fruit"和"Amount"变量
BuyerID Fruit Amount Total Count
879 "Banana" "Apple" 4 3 7 2
765 "Strawberry" "Apple" "Orange" 1 2 4 7 3
123 "Orange" "Banana" 1 1 1 3 2
11 "Strawberry" 3 3 1
773 "Kiwi" "Banana" 1 2 3 2
Run Code Online (Sandbox Code Playgroud)
我已经尝试过使用c()和rbind(),但是它们没有产生我想要的结果 - 我在这里尝试了一些提示:data.frame行也是一个列表但是我不太确定这是否是最好的方法简化我的数据.
这可能是因为我可能更容易处理较少的变量来计算某些项目的出现(例如60%的买家购买香蕉).
我希望这是可行的 - 我也对任何建议持开放态度.任何解决方案升值
谢谢.
mne*_*nel 11
尝试复制数据并使用data.table
DT <- data.frame(
BuyerID = c(879,765,123,11,773),
Fruit.1 = c('Banana','Strawberry','Orange','Strawberry','Kiwi'),
Fruit.2 = c('Apple','Apple','Banana',NA,'Banana'),
Fruit.3 = c( NA, 'Orange',NA,NA,NA),
Amount.1 = c(4,1,1,3,1), Amount.2 = c(3,2,1,NA,2), Amount.3 = c(NA,4,1,NA,NA),
Total = c(7,7,3,3,3),
Count = c(2,3,2,1,2),
stringsAsFactors = FALSE)
# reshaping to long form and data.table
library(data.table)
DTlong <- data.table(reshape(DT, varying = list(Fruit = 2:4, Amount = 5:7),
direction = 'long'))
# create lists (without NA values)
# also adding count and total columns
# by using <- to save Fruit and Amount for later use
DTlist <- DTlong[, list(Fruit <- list(as.vector(na.omit(Fruit.1))),
Amount <- list(as.vector(na.omit(Amount.1))),
Count = length(unlist(Fruit)),
Total = sum(unlist(Amount))),
by = BuyerID]
BuyerID V1 V2 Count Total
1: 879 Banana,Apple 4,3 2 7
2: 765 Strawberry,Apple,Orange 1,2,4 3 7
3: 123 Orange,Banana 1,1,1 2 3
4: 11 Strawberry 3 1 3
5: 773 Kiwi,Banana 1,2 2 3
Run Code Online (Sandbox Code Playgroud)
@RicardoSaporta编辑:
您可以跳过重塑步骤,如果您愿意,使用list(list(c(....)))
这可能会节省相当多的执行时间(缺点是它不添加NA空格).但是,正如@Marius指出的那样,DTlong上面的内容可能更容易使用.
DT <- data.table(DT)
DT[, Fruit := list(list(c( Fruit.1, Fruit.2, Fruit.3))), by=BuyerID]
DT[, Ammount := list(list(c(Amount.1, Amount.2, Amount.3))), by=BuyerID]
# Or as a single line
DT[, list( Fruit = list(c( Fruit.1, Fruit.2, Fruit.3)),
Ammount = list(c(Amount.1, Amount.2, Amount.3)),
Total, Count), # other columns used
by = BuyerID]
Run Code Online (Sandbox Code Playgroud)
这是一个带有基础包的解决方案.这就像泰勒解决方案,但只有一个适用.
res <- apply(DT,1,function(x){
data.frame(Fruit= paste(na.omit(x[2:4]),collapse=' '),
Amount = paste(na.omit(x[5:7]),collapse =','),
Total = sum(as.numeric(na.omit(x[5:7]))),
Count = length(na.omit(x[2:4])))
})
do.call(rbind,res)
Fruit Amount Total Count
1 Banana Apple 4, 3 7 2
2 Strawberry Apple Orange 1, 2, 4 7 3
3 Orange Banana 1, 1, 1 3 2
4 Strawberry 3 3 1
5 Kiwi Banana 1, 2 3 2
Run Code Online (Sandbox Code Playgroud)
我也会用grep改变索引号,就像这样
Fruit = gregexpr('Fruit[.][0-9]', colnames(dat)) > 0
Amount = gregexpr('Amount[.][0-9]', colnames(dat)) > 0
x[2:4] replace by x[which(Fruit)]....
Run Code Online (Sandbox Code Playgroud)
编辑添加一些基准测试.
library(microbenchmark)
library(data.table)
microbenchmark(ag(),mn(), am(), tr())
Unit: milliseconds
expr min lq median uq max
1 ag() 11.584522 12.268140 12.671484 13.317934 109.13419
2 am() 9.776206 10.515576 10.798504 11.437938 137.44867
3 mn() 6.470190 6.805646 6.974797 7.290722 48.68571
4 tr() 1.759771 1.929870 2.026960 2.142066 7.06032
Run Code Online (Sandbox Code Playgroud)
对于小型数据框架,Tyler Rinker是赢家!我怎么解释这个(只是一个猜测)
这是一个非常糟糕的主意,但在这里是基础data.frame.它的工作原理data.frame实际上是一个等长矢量列表.你可以强制data.frame在单元格中存储向量,但它需要一些hackery.我建议其他格式,包括Marius的建议或列表.
DT <- data.frame(
BuyerID = c(879,765,123,11,773),
Fruit.1 = c('Banana','Strawberry','Orange','Strawberry','Kiwi'),
Fruit.2 = c('Apple','Apple','Banana',NA,'Banana'),
Fruit.3 = c( NA, 'Orange',NA,NA,NA),
Amount.1 = c(4,1,1,3,1), Amount.2 = c(3,2,1,NA,2), Amount.3 = c(NA,4,1,NA,NA),
stringsAsFactors = FALSE)
DT2 <- DT[, 1, drop=FALSE]
DT2$Fruit <- apply(DT[, 2:4], 1, function(x) unlist(na.omit(x)))
DT2$Amount <- apply(DT[, 5:7], 1, function(x) unlist(na.omit(x)))
DT2$Total <- sapply(DT2$Amount, sum)
DT2$Count <- sapply(DT2$Fruit, length)
Run Code Online (Sandbox Code Playgroud)
产量:
> DT2
BuyerID Fruit Amount Total Count
1 879 Banana, Apple 4, 3 7 2
2 765 Strawberry, Apple, Orange 1, 2, 4 7 3
3 123 Orange, Banana 1, 1, 1 3 2
4 11 Strawberry 3 3 1
5 773 Kiwi, Banana 1, 2 3 2
Run Code Online (Sandbox Code Playgroud)