我有一个像:
这样的数据集Company,Product,Users MSFT,Office,1000 MSFT,VS,4000 GOOG,gmail,3203 GOOG,appengine,45454 MSFT,Windows,1500 APPL,iOS,6000 APPL,iCloud,3442
我正在编写一个函数来为每个公司的第n个产品返回一个数据框,用#34;用户"所以rankcompany(1)的输出应该是:
Company Prodcut Users APPL APPL iOS 6000 GOOG GOOG appengine 45454 MSFT MSFT VS 4000
该功能如下:
rankcompany <- function(num=1){
#Read data file
company_data <- read.csv("company.csv",stringsAsFactors = FALSE)
#split by company
split_data <- split(company_data, company_data$Company)
#sort and select the nth row
selected <- lapply(split_data, function(df) {
df <- df[order(-df$Users, df$Product),]
df[num,]
})
#compose output data frame
#this part needs to be smarter??
len <- length(selected)
selected_df <- data.frame(Company=character(len),Prodcut=character(len), Users=integer(len),stringsAsFactors = FALSE)
row.names(selected_df) <- names(selected)
for (n in names(selected)){
print(str(selected[[n]]))
selected_df[n,] <- selected[[n]][1,]
}
selected_df
}
我将输入数据框拆分为一个列表,然后执行排序和选择,然后尝试将结果合并到输出数据框中&#34; selected_df&#34;
我是R的新手,我可以更聪明地完成合并。或者我应该首先避免分裂?有什么建议吗?
由于
答案 0 :(得分:5)
您可以使用dplyr
:
rankcompany <- function(d, num=1) {
d %>% group_by(Company) %>% arrange(desc(Users)) %>% slice(num)
}
然后你可以这样做:
rankcompany(d,2)
或:
d %>% rankcompany(1)
答案 1 :(得分:4)
根据@DMT的评论 我用以下代码替换了合并代码:
selected_df <- rbindlist(selected)
selected_df <- as.data.frame(selected_df)
row.names(selected_df) <- names(selected)
selected_df
它运作正常。
答案 2 :(得分:2)
如果您喜欢split
和lapply
的清晰度,则可以使用功能更短的版本。
rankcompany <- function(N){
byCompany <- split(df, sorted$Company)
ranks <- lapply(byCompany,
function(x)
{
r <- which(rank(-x$Users)==N)
x[r,]
})
do.call("rbind", ranks)
}
rankcompany(1)
> rankcompany(1)
Company Product Users
APPL MSFT VS 4000
GOOG GOOG appengine 45454
MSFT APPL iOS 6000
答案 3 :(得分:2)
如果您使用的是rbindlist
,则可能需要在执行此操作之前转换为data.frame
:
library(data.table) ## 1.9.2+
n <- 1L
setDT(company_data)[order(-Users), .SD[n], keyby=Company]
# Company Product Users
#1: APPL iOS 6000
#2: GOOG appengine 45454
#3: MSFT VS 4000
setDT
通过引用将<{1}}转换为data.frame
(无任何额外的副本/内存使用情况)。然后我们按data.table
列的降序对data.table进行排序,然后按 Users
对 group进行排序,对于每个组,我们获取company
行来自 D ata(n
)的 S ubset。
在你的情况下,或许,
.SD
但是之前的解决方案是一个更有效,更容易解决问题的单线程。
DT <- rbindlist(selected)
DT[order(-Users), .SD[n], keyby=Company]