基于拆分和列的规范化(重塑)数据框
Posted
技术标签:
【中文标题】基于拆分和列的规范化(重塑)数据框【英文标题】:Normalizing(Reshaping) data frame based on split and columns 【发布时间】:2013-11-08 13:05:49 【问题描述】:我有一个包含
的数据框df
Date name score
12/09/2012 Mahesh\nRahul 120
13/09/2012 abc\nxyz\nrep 110
...........................
我已经尝试过这个以获得原子
name1=str_split(df[,2],"\n")
但不知道如何再次关联,使数据框标准化以便我可以得到的最佳方法是什么
df
Date name score
12/09/2012 Mahesh 120
12/09/2012 Rahul 120
13/09/2012 abc 110
13/09/2012 xyz 110
13/09/2012 rep 110
...........................
任何有助于在 R 中规范化长数据帧。
编辑
请注意,这只是一个可重复的示例,我的 name 列中有多个名称,并且名称的数量从一行到另一行不等。谢谢。
dput(df) structure(list(Date = structure(1:2, .Label = c("12/09/2012", "13/09/2012 "), class = "factor"), name = structure(c(2L, 1L), .Label = c("abc\nxyz", "Mahesh\nRahul"), class = "factor"), score = structure(c(2L, 1L), .Label = c("110", "120"), class = "factor")), .Names = c("Date", "name", "score"), row.names = c(NA, -2L), class = "data.frame")
【问题讨论】:
请查看link。一个好的可重复示例将帮助其他人更轻松地解决您的问题。 请提供dput(df)
的输出,以便我们可以在我们这边复制df
您混淆了原子性的含义。要真正让data.frame
成为原子向量,只需使用unlist( data.frame )
,但这不会得到你想要的输出。这是一个关于重塑数据的问题。
@geektrader dput(df) structure(list(Date = structure(1:2, .Label = c("12/09/2012", "13/09/2012"), class= "因子"), 名称 = 结构(c(2L, 1L), .Label = c("abc\nxyz", "Mahesh\nRahul"), class= "因子"), 分数 = 结构(c(2L, 1L) ), .Label = c("110", "120"), class= "factor")), .Names = c("Date", "name", "score"), row.names = c(NA, -2L), class= "data.frame")
下次我会记住如何正确编写可重现的考试,谢谢。
【参考方案1】:
这是一个基于 R 的解决方案
更新
> Names <- strsplit(df$name, "\n")
> n <- sapply(Names, length)
> data.frame(cbind(apply(df[,-2], 2, function(x) rep(x, n)),
name=unlist(Names)), row.names = NULL)[,c(1,3,2)]
Date name score
1 12/09/2012 Mahesh 120
2 12/09/2012 Rahul 120
3 13/09/2012 abc 110
4 13/09/2012 xyz 110
5 13/09/2012 rep 110
df
在哪里:
> dput(df)
structure(list(Date = c("12/09/2012", "13/09/2012"), name = c("Mahesh\nRahul",
"abc\nxyz\nrep"), score = c(120, 110)), .Names = c("Date", "name",
"score"), row.names = c(NA, -2L), class = "data.frame")
【讨论】:
+1 我同意马修的观点。这没有什么丑陋的。很实用的解决方案。我认为它确实假设所有名称的拆分都是相等的,对吗?还是我误解了? 感谢@MatthewPlourde 和 SimonO101,将删除丑陋的形容词。 注意,这两种方式都假设每行只有两个名字。 data.frame(..., check.names = FALSE) 中的错误:参数暗示不同的行数:R base sol dat1 @Jilber,您需要在这方面做更多工作,以使其适用于“名称”列中的“不平衡”数据。【参考方案2】:使用data.table
相对容易(而且速度显然很快)。
require( data.table )
dt <- data.table( df )
dt[ , list( name = unlist( strsplit( name , "\n" ) ) ) , by = list( Date , score ) ]
# Date score name
#1: 12/09/2012 120 Mahesh
#2: 12/09/2012 120 Rahul
#3: 13/09/2012 110 abc
#4: 13/09/2012 110 xyz
作为注释,我将df
用作以下数据(注意character
类超过factor
类出现在您的实际数据中......
df <- read.delim( text = "Date name score
12/09/2012 'Mahesh\nRahul' 120
13/09/2012 'abc\nxyz' 110" ,
sep = "" , h = TRUE , quote = "\'" , stringsAsFactors = FALSE )
【讨论】:
@Aashu 你读过我关于我的数据与你的数据有何不同的说明吗?具体来说,您的数据中有factor
。没有你得到的东西,你的评论不是很有帮助。正如我展示的那样,该代码适用于输入数据。
df=read.csv("abc.csv", header = TRUE,quote = "\'" , check.names = TRUE,stringsAsFactors = FALSE ) ,希望能满足你的条件。跨度>
@Aashu 我认为您不需要quote
(我不确定 - 我添加它是为了在我从您的 OP 复制/粘贴数据时正确读取数据)。我建议您以正常方式阅读您的数据,然后只需添加stringsAsFactors = FALSE
。【参考方案3】:
这里已经有很好的答案,但这是使用rle
和inverse.rle
函数的base R 的另一种方式。 @Jilber 的基本 R 解决方案更优雅,但如果您的字符串有两个以上的名称,这种方式将起作用。
df <- read.table(text='Date name score
12/09/2012 "Mahesh\nRahul" 120
13/09/2012 "abc\nxyz\nrep" 110', header=TRUE, stringsAsFactors=FALSE)
ns <- strsplit(df$name, '\n')
result <- lapply(lapply(lapply(df, rle), `[[<-`, 'lengths', sapply(ns, length)), inverse.rle)
transform(data.frame(result), name=unlist(ns))
# Date name score
# 1 12/09/2012 Mahesh 120
# 2 12/09/2012 Rahul 120
# 3 13/09/2012 abc 110
# 4 13/09/2012 xyz 110
# 5 13/09/2012 rep 110
【讨论】:
+1 仅适用于readClipboard()
!多么方便的功能,我从来不知道。
@SimonO101 谢谢,不过我删除了它。这种方式无法正确读取换行符。
您能否在您的帖子中发布str(df)
的输出,或者更好的是dput(df[1:3, ])
的输出?【参考方案4】:
要添加替代方案,您可以使用scan
轻松分隔字符串,使用rep
和cbind
得到最终的data.frame
df
# Date name score
# 1 12/09/2012 Mahesh\nRahul 120
# 2 13/09/2012 abc\nxyz\nrep 110
scan(text=as.character(df$name), what = "")
# Read 5 items
# [1] "Mahesh" "Rahul" "abc" "xyz" "rep"
cbind(df[rep(rownames(df),
sapply(gregexpr("\n", df$name), length)+1),
c("Date", "score")],
name = scan(text=as.character(df$name), what = ""))
# Date score name
# 1 12/09/2012 120 Mahesh
# 1.1 12/09/2012 120 Rahul
# 2 13/09/2012 110 abc
# 2.1 13/09/2012 110 xyz
# 2.2 13/09/2012 110 rep
read.table
也可以拆分连接的列:
read.table(text = as.character(df$name), sep = "\n", header = FALSE)
# V1
# 1 Mahesh
# 2 Rahul
# 3 abc
# 4 xyz
# 5 rep
【讨论】:
以上是关于基于拆分和列的规范化(重塑)数据框的主要内容,如果未能解决你的问题,请参考以下文章