Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/extjs/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
R 展平分隔的复合列_R - Fatal编程技术网

R 展平分隔的复合列

R 展平分隔的复合列,r,R,我在R中得到了一个数据帧,其中一个字段是复合的(分隔的)。下面是我得到的一个例子: users=c(1,2,3) items=c("23 77 49", "10 18 28", "20 31 84") df = data.frame(users,items) (我不构建它;这只是为了说明。) 我想展平第二列,以便获得(非唯一的)用户ID列表和每行一项。因此,我想以: user item 1 23 1 77 1 49 2 10 2

我在R中得到了一个数据帧,其中一个字段是复合的(分隔的)。下面是我得到的一个例子:

users=c(1,2,3)
items=c("23 77 49", "10 18 28", "20 31 84")
df = data.frame(users,items)
(我不构建它;这只是为了说明。)

我想展平第二列,以便获得(非唯一的)用户ID列表和每行一项。因此,我想以:

user   item
1        23
1        77
1        49
2        10
2        18
2        28
3        20
3        31
3        84
我试过:

data.frame(user = df$users, item = unlist(strsplit(as.character(df$items), " "))) 
但我得到“参数意味着不同的行数”。我明白为什么,但找不到解决方案来给我想要的结果。有什么想法吗


还有,当我得到超过2000万行时,最有效的方法是什么?

items
items这里是一个
dplyr
解决方案

items <- strsplit(df$items, " ")
data.frame(user = rep(df$users, sapply(items, length)), item = unlist(items))

##   user item                                                                                                                                                                                                                                
## 1    1   23                                                                                                                                                                                                                                
## 2    1   77                                                                                                                                                                                                                                
## 3    1   49                                                                                                                                                                                                                                
## 4    2   10                                                                                                                                                                                                                                
## 5    2   18                                                                                                                                                                                                                                
## 6    2   28                                                                                                                                                                                                                                
## 7    3   20                                                                                                                                                                                                                                
## 8    3   31                                                                                                                                                                                                                                
## 9    3   84  
users=c(1,2,3)
items=c("23 77 49", "10 18 28", "20 31 84")
df = data.frame(users,items,stringsAsFactors=FALSE)
rbind_all(do(df %.% group_by(users), 
          .f = function(d) data.frame(d[,1,drop=FALSE], 
              items = unlist(strsplit(d[['items']],' ')), 
           stringsAsFactors=FALSE)))
如果有一个
展开
功能,也就是说,与
总结

如果下面的方法行得通

df %.% group_by(users) %.% expand(unlist(strsplit(items,' ')))

下面是一个
dplyr
解决方案

users=c(1,2,3)
items=c("23 77 49", "10 18 28", "20 31 84")
df = data.frame(users,items,stringsAsFactors=FALSE)
rbind_all(do(df %.% group_by(users), 
          .f = function(d) data.frame(d[,1,drop=FALSE], 
              items = unlist(strsplit(d[['items']],' ')), 
           stringsAsFactors=FALSE)))
如果有一个
展开
功能,也就是说,与
总结

如果下面的方法行得通

df %.% group_by(users) %.% expand(unlist(strsplit(items,' ')))

如果您愿意安装我的“SOfun”软件包或加载我的,并且如果每个“item”字符串中有相同数量的项(在您的示例中,有3个),则以下可能是一个选项:

library(reshape2)
library(data.table)

melt(concat.split.DT(indf, "items", " "), id.vars="users")
这里有一个例子

示例数据:3行、3000行和3000000行 我添加了一个“id”列,以便您可以比较两个选项的输出

## your sample data.frame
df <- data.frame(users=c(1,2,3),
                 items=c("23 77 49", "10 18 28", "20 31 84"))

## extended to 3000 rows
df1k <- df[rep(rownames(df), 1000), ]
df1k$id <- sequence(nrow(df1k))

## extended to 3 million rows
df1m <- df1M <- df[rep(rownames(df), 1000000), ]
df1m$id <- sequence(nrow(df1m))
下面是一些测试Jake回答速度的函数,还有这个。稍后我也会尝试使用“dplyr”进行更新

在300万行上测试(仅一次)

这里的时间单位是秒

system.time(fun1(df1m))
#    user  system elapsed 
#    7.71    0.94    8.69 
system.time(fun2(df1m))
#    user  system elapsed 
#  177.80    0.50  178.97 

更新 @杰克在评论中提出了一个很好的观点,即添加一个“id”在时间安排上有很大的不同。我添加它只是为了方便比较两种
数据.table
方法的输出,以查看结果是否相同

fun1
fun2
中删除“id”列并删除对“id”的引用,我们可以得到以下信息:

microbenchmark(fun1a(df1M), fun2a(df1M), fun3(df1M), times = 5)
# Unit: seconds
#         expr       min        lq    median        uq       max neval
#  fun1a(df1M)  2.307313  2.420845  2.630284  2.822011  3.074464     5
#  fun2a(df1M) 12.480502 12.491783 12.761392 13.069169 13.733686     5
#   fun3(df1M) 13.976329 14.281856 14.471252 15.041450 15.089593     5
上述基准还包括
fun3
,这是@mnel的“dplyr”方法

fun3 <- function(indf) {
  rbind_all(do(indf %.% group_by(users), 
               .f = function(d) data.frame(
                 d[,1,drop=FALSE], 
                 items = unlist(strsplit(as.character(d[['items']]),' ')), 
                 stringsAsFactors=FALSE)))
}

fun3如果您愿意安装我的“SOfun”软件包或加载我的,并且如果每个“item”字符串中有相同数量的项(在您的示例中,有3个),则以下可能是一个选项:

library(reshape2)
library(data.table)

melt(concat.split.DT(indf, "items", " "), id.vars="users")
这里有一个例子

示例数据:3行、3000行和3000000行 我添加了一个“id”列,以便您可以比较两个选项的输出

## your sample data.frame
df <- data.frame(users=c(1,2,3),
                 items=c("23 77 49", "10 18 28", "20 31 84"))

## extended to 3000 rows
df1k <- df[rep(rownames(df), 1000), ]
df1k$id <- sequence(nrow(df1k))

## extended to 3 million rows
df1m <- df1M <- df[rep(rownames(df), 1000000), ]
df1m$id <- sequence(nrow(df1m))
下面是一些测试Jake回答速度的函数,还有这个。稍后我也会尝试使用“dplyr”进行更新

在300万行上测试(仅一次)

这里的时间单位是秒

system.time(fun1(df1m))
#    user  system elapsed 
#    7.71    0.94    8.69 
system.time(fun2(df1m))
#    user  system elapsed 
#  177.80    0.50  178.97 

更新 @杰克在评论中提出了一个很好的观点,即添加一个“id”在时间安排上有很大的不同。我添加它只是为了方便比较两种
数据.table
方法的输出,以查看结果是否相同

fun1
fun2
中删除“id”列并删除对“id”的引用,我们可以得到以下信息:

microbenchmark(fun1a(df1M), fun2a(df1M), fun3(df1M), times = 5)
# Unit: seconds
#         expr       min        lq    median        uq       max neval
#  fun1a(df1M)  2.307313  2.420845  2.630284  2.822011  3.074464     5
#  fun2a(df1M) 12.480502 12.491783 12.761392 13.069169 13.733686     5
#   fun3(df1M) 13.976329 14.281856 14.471252 15.041450 15.089593     5
上述基准还包括
fun3
,这是@mnel的“dplyr”方法

fun3 <- function(indf) {
  rbind_all(do(indf %.% group_by(users), 
               .f = function(d) data.frame(
                 d[,1,drop=FALSE], 
                 items = unlist(strsplit(as.character(d[['items']]),' ')), 
                 stringsAsFactors=FALSE)))
}

fun3每个“项目”行中的项目数量是否始终相同?@AnandaMahto No。每行可以有不同数量的分隔项目。每个“项目”中的项目数量是否始终相同行?@AnandaMahto-No。每行可以有不同数量的分隔项。添加
id
列似乎可以改变一些事情lot@JakeBurkhead你说得对。我添加了它,这样可以更容易地比较和验证输出是否包含相同的数据。我已经更新了一个基准,显示了删除“id”后的情况。感谢更新基准。这些都是我在没有
id
的情况下运行它时看到的情况。添加
id
列似乎改变了很多事情lot@JakeBurkhead你说得对。我添加了它,这样可以更容易地比较和验证输出是否包含相同的数据。我已经更新了一个基准,显示了删除“id”后的情况。感谢更新基准。这些都是我在没有
id
的情况下运行它时看到的情况。这是一些不错的性能。这似乎反转了输出中的“用户”列。你知道为什么吗?@AnandaMahto-它确实对订单做了一些奇怪的事情。不完全相反。我可能会报告这一点。@AnandaMahto--这似乎是由于
用户类的原因。看,这是一场精彩的演出。这似乎反转了输出中的“用户”列。你知道为什么吗?@AnandaMahto-它确实对订单做了一些奇怪的事情。不完全相反。我可能会报告这一点。@AnandaMahto--这似乎是由于
用户类的原因。作为一种非常简单易读的方法,我喜欢
数据。table
选项a lot+1作为一种非常简单易读的方法,我喜欢
数据。table
选项a lot+1