【问题标题】:Excel or R: reshaping dataExcel 或 R:重塑数据
【发布时间】:2017-09-18 04:46:02
【问题描述】:

我有一些看起来像这样的数据:

ID Data

1  a b c 
2  a b c a b c
3  a b c 
4  a b c a b c a b c a b c
5  a b c a b c a b c

我想要它在下面

ID Data

1 a b c
2 a b c
2 a b c
3 a b c
4 a b c
4 a b c
4 a b c
4 a b c
5 a b c
5 a b c
5 a b c

abc 位于不同的列单元格中,因此 Data 实际上是很多列。如果需要,我可以将它们连接起来。

基本上 a bc 是相关的,但对于某些 ID,我有多个结果,我希望数据采用长格式而不是宽格式,但保留每一行的 ID。

如果这也更容易的话,我可以用 R 来做。

输入:

structure(list(ID = c(9999812L, 999908L, 9993595L, 9992905L, 
9989664L, 9984487L, 9980956L, 9980112L, 9980091L, 9979915L, 9979613L, 
9979400L, 9978215L, 9976882L, 9975335L, 9974511L, 9973804L, 9973025L
), a = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
1L, 1L, 1L, 1L, 1L, 1L, 1L), .Label = "a", class = "factor"), 
    b = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
    1L, 1L, 1L, 1L, 1L, 1L, 1L), .Label = "b", class = "factor"), 
    c = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
    1L, 1L, 1L, 1L, 1L, 1L, 1L), .Label = "c", class = "factor"), 
    a.1 = structure(c(2L, 1L, 1L, 1L, 1L, 2L, 1L, 1L, 1L, 1L, 
    1L, 2L, 1L, 1L, 2L, 1L, 2L, 2L), .Label = c("", "a"), class = "factor"), 
    b.1 = structure(c(2L, 1L, 1L, 1L, 1L, 2L, 1L, 1L, 1L, 1L, 
    1L, 2L, 1L, 1L, 2L, 1L, 2L, 2L), .Label = c("", "b"), class = "factor"), 
    c.1 = structure(c(2L, 1L, 1L, 1L, 1L, 2L, 1L, 1L, 1L, 1L, 
    1L, 2L, 1L, 1L, 2L, 1L, 2L, 2L), .Label = c("", "c"), class = "factor"), 
    a.2 = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
    1L, 2L, 1L, 1L, 2L, 1L, 1L, 2L), .Label = c("", "a"), class = "factor"), 
    b.2 = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
    1L, 2L, 1L, 1L, 2L, 1L, 1L, 2L), .Label = c("", "b"), class = "factor"), 
    c.2 = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
    1L, 2L, 1L, 1L, 2L, 1L, 1L, 2L), .Label = c("", "c"), class = "factor"), 
    a.3 = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
    1L, 1L, 1L, 1L, 2L, 1L, 1L, 2L), .Label = c("", "a"), class = "factor"), 
    b.3 = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
    1L, 1L, 1L, 1L, 2L, 1L, 1L, 2L), .Label = c("", "b"), class = "factor"), 
    c.3 = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
    1L, 1L, 1L, 1L, 2L, 1L, 1L, 2L), .Label = c("", "c"), class = "factor"), 
    a.4 = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
    1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L), .Label = c("", "a"), class = "factor"), 
    b.4 = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
    1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L), .Label = c("", "b"), class = "factor"), 
    c.4 = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
    1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L), .Label = c("", "c"), class = "factor")), .Names = c("ID", 
"a", "b", "c", "a.1", "b.1", "c.1", "a.2", "b.2", "c.2", "a.3", 
"b.3", "c.3", "a.4", "b.4", "c.4"), class = "data.frame", row.names = c(NA, 
-18L))

【问题讨论】:

  • 有列标题吗? (例如,a 总是“名字”吗?是否只有这三种数据类型,或者是否有列 d 等您只想忽略?
  • 如果 'a', 'b', 'c' 在不同的列中,那么你会有不同的列名。
  • 每一行都有一个唯一的 id。
  • 我可以设置标题,但长度不相等,我不希望行 ID 后跟空白单元格。第一个表中的 ID 是唯一的。它不会在转换时出现,因此它可以解释具有多个 a、b 和 c 的第一行中的行
  • 是的,我使用的是 read.table("clipboard", header=T, fill=T) 但它之前没有出现。这更准确,但我用 b 和 c 替换了我的字符串

标签: r excel data-manipulation


【解决方案1】:

有了你的初始数据,你可以使用“stringr”和“reshape2”来融合数据。

dt <- data.frame(x = 1:5, y = c( "a b c" , "a b c a b c","a b c","a b c a b c a b c a b c", "a b c a b c a b c"))

library("stringr")
library("reshape2")
maxlen <- max(lengths(str_extract_all(dt$y,"(\\w)\\s(\\w)\\s(\\w)(\\1\\s\\2\\s\\3)*")))

list_lists <- str_extract_all(dt$y,"(\\w)\\s(\\w)\\s(\\w)(\\1\\s\\2\\s\\3)*")

li <- lapply(list_lists, `length<-`,maxlen)

dtnew <- data.frame(x =cbind(dt$x),do.call("rbind",li))
dtnew1 <- melt(dtnew,id.vars="x")
dtnew1 <- dtnew1[!is.na(dtnew1$value),]
dtnew1[order(dtnew1$x),]

   > dtnew1[order(dtnew1$x),c(1,3)]
   x value
1  1 a b c
2  2 a b c
7  2 a b c
3  3 a b c
4  4 a b c
9  4 a b c
14 4 a b c
19 4 a b c
5  5 a b c
10 5 a b c
15 5 a b c
> 

编辑:对于更新的数据,创建一个名为“concat”的字段,它是列“a”到“c.4”的连接值

您可以使用:concat &lt;- data.frame(concat=do.call("paste0",dt[,2:length(dt)])) 连接字段

然后分配dt$concat &lt;- concat

library("stringr")
library("reshape2")

maxlen <- max(lengths(str_extract_all(dt$concat,"(\\w)(\\w)(\\w)")))

list_lists <- str_extract_all(dt$concat,"(\\w)(\\w)(\\w)")

li <- lapply(list_lists, `length<-`,maxlen)

dtnew <- data.frame(x =cbind(dt$ID),y=do.call("rbind",li))
dtnew1 <- melt(dtnew,id.vars="x")
dtnew1 <- dtnew1[!is.na(dtnew1$value),]
dtnew1[order(dtnew1$x),c(1,3)]

> dtnew1[order(dtnew1$x),c(1,3)]
         x value
2   999908   abc
18 9973025   abc
36 9973025   abc
54 9973025   abc
72 9973025   abc
90 9973025   abc
17 9973804   abc
35 9973804   abc
16 9974511   abc
15 9975335   abc
33 9975335   abc
51 9975335   abc
69 9975335   abc
14 9976882   abc
13 9978215   abc
12 9979400   abc
30 9979400   abc
48 9979400   abc
11 9979613   abc
10 9979915   abc
9  9980091   abc
8  9980112   abc
7  9980956   abc
6  9984487   abc
24 9984487   abc
5  9989664   abc
4  9992905   abc
3  9993595   abc
1  9999812   abc
19 9999812   abc
> 

【讨论】:

  • 由于我的字符串的性质,您能否假设每个 a、b 或 c 位于不同的列中。我把它放在一个有 60K 行和 43 列的数据框中(大多数只有前 4 列中的数据,其余的通常是空白的)
  • 我猜想在 ID 之后,连接每组 3 列,将其融合,然后 cSplit 将其退出
  • 好的,这适用于测试数据,但是在我的数据中,a 是一个字符串,其中可能有空格。那会抛出 \\w 吗?我可以在每个字符串末尾添加一个 , 作为分隔符
  • 所以 a 可以是“Hello world” b 可以是“字符串”,c 可以是“我喜欢海龟”。他们只使用没有特殊字符的字母和空格
  • 如果你想匹配 x str_extract_all(x,"[\\w\\s]{1,}"),基本上你有调整str_extract 每次如果模式发生变化,我建议您使用 stringr 和 str_view 在 html 视图中查看匹配项,这将增加您对正则表达式的直觉
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-04-06
  • 1970-01-01
  • 2014-03-10
  • 2017-11-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多