【问题标题】:Restructure using tidyr使用 tidyr 进行重组
【发布时间】:2017-03-24 18:56:56
【问题描述】:

我有 1 个长字符串(每行)内的数据。基本上它是用分号分隔的,列/答案由= 分隔。我正在尝试执行以下操作:

当前结构:

 Row1: “Column1 = blah1;Column2 = blah2;Column3 = blah3;Column4 = blah4” 
 Row2: “Column1 = blah1;Column2 = blah2;Column3 = blah3;Column4 = blah4”

转换为 ->

Column1|Column2|Column3|Column4
blah1|blah2|blah3|blah4
blah1|blah2|blah3|blah4

我相信 R 中的 tidyr 包是可行的方法,但我无法弄清楚。

这是我使用 tidyr 所得到的,但我仍然收到错误:

# CREATE TEST DATA
mydata <- as.data.frame(c("Column1 = blah1; Column2 =  blah2; Column3 = blah3; Column4 = blah4","Column1 = blah1; Column2 =  blah2; Column3 = blah3; Column4 = blah4","Column1 = blah1; Column2 =  blah2; Column3 = blah3; Column4 = blah4"))
names(mydata) <- "TEST"

# Create dummy vector
x <- vector(mode="numeric", length=0)

# Separate by ;
x <- separate(mydata, TEST, x, sep = ";" )

非常感谢任何帮助。

【问题讨论】:

  • 已编辑以修复格式。粘贴代码时,您可以选择刚刚粘贴的内容,然后点击Ctrl+k 或单击{} 图标,以便将其正确格式化为代码。此外,虽然您尝试制作可重现示例的方式很好,但如果您将问题编辑为 1)解释测试数据的所需输出是什么,以及 2)描述您遇到的错误,这可能会有所帮助。
  • 感谢您的提示!将针对我的下一个问题进行调整。

标签: r tidyr


【解决方案1】:

我将使用dplyr pipes 一步一步地展示如何做到这一点,在每一步之后打印输出,以便您了解数据结构是如何演变的。

mydata <- as.data.frame(c("Column1 = blah1; Column2 = blah2; Column3 = blah3; Column4 = blah4","Column1 = blah1; Column2 = blah2; Column3 = blah3; Column4 = blah4","Column1 = blah1; Column2 = blah2; Column3 = blah3; Column4 = blah4")) 
names(mydata) <- "TEST"

看起来是这样的:

> mydata
                                                                TEST
1 Column1 = blah1; Column2 = blah2; Column3 = blah3; Column4 = blah4
2 Column1 = blah1; Column2 = blah2; Column3 = blah3; Column4 = blah4
3 Column1 = blah1; Column2 = blah2; Column3 = blah3; Column4 = blah4

以下是转换它的步骤:

library(dplyr)
library(tidyr)

1) 以变量分隔

mydata %>% 
separate(rows, into=paste0("Column", 1:4), sep=";")

输出:

          Column1          Column2          Column3          Column4
1 Column1 = blah1  Column2 = blah2  Column3 = blah3  Column4 = blah4
2 Column1 = blah1  Column2 = blah2  Column3 = blah3  Column4 = blah4
3 Column1 = blah1  Column2 = blah2  Column3 = blah3  Column4 = blah4

2) 添加行标识符

mydata %>% 
  separate(TEST, into=paste0("Column", 1:4), sep=";") %>% 
  mutate(row=row.names(mydata))

输出:

          Column1          Column2          Column3          Column4 row
1 Column1 = blah1  Column2 = blah2  Column3 = blah3  Column4 = blah4   1
2 Column1 = blah1  Column2 = blah2  Column3 = blah3  Column4 = blah4   2
3 Column1 = blah1  Column2 = blah2  Column3 = blah3  Column4 = blah4   3

3) 重新格式化为 long

mydata %>% 
  separate(TEST, into=paste0("Column", 1:4), sep=";") %>% 
  mutate(row=row.names(mydata)) %>% 
  gather("key", "value", -row)

输出:

   row     key            value
1    1 Column1  Column1 = blah1
2    2 Column1  Column1 = blah1
3    3 Column1  Column1 = blah1
4    1 Column2  Column2 = blah2
5    2 Column2  Column2 = blah2
6    3 Column2  Column2 = blah2
7    1 Column3  Column3 = blah3
8    2 Column3  Column3 = blah3
9    3 Column3  Column3 = blah3
10   1 Column4  Column4 = blah4
11   2 Column4  Column4 = blah4
12   3 Column4  Column4 = blah4

4) 然后提取数据

mydata %>% 
  separate(TEST, into=paste0("Column", 1:4), sep=";") %>% 
  mutate(row=row.names(mydata)) %>% 
  gather("key", "value", -row) %>% 
  extract(value, into="value", regex=".* = (.*)$")

输出:

   row     key value
1    1 Column1 blah1
2    2 Column1 blah1
3    3 Column1 blah1
4    1 Column2 blah2
5    2 Column2 blah2
6    3 Column2 blah2
7    1 Column3 blah3
8    2 Column3 blah3
9    3 Column3 blah3
10   1 Column4 blah4
11   2 Column4 blah4
12   3 Column4 blah4

5) 如果需要,将其展开成宽幅格式

mydata %>% 
  separate(TEST, into=paste0("Column", 1:4), sep=";") %>% 
  mutate(row=row.names(mydata)) %>% 
  gather("key", "value", -row) %>% 
  extract(value, into="value", regex=".* = (.*)$") %>% 
  spread(key, value)

输出:

  row Column1 Column2 Column3 Column4
1   1   blah1   blah2   blah3   blah4
2   2   blah1   blah2   blah3   blah4
3   3   blah1   blah2   blah3   blah4

6) 如果需要,删除行标识符

mydata %>% 
  separate(TEST, into=paste0("Column", 1:4), sep=";") %>% 
  mutate(row=row.names(mydata)) %>% 
  gather("key", "value", -row) %>% 
  extract(value, into="value", regex=".* = (.*)$") %>% 
  spread(key, value) %>% 
  select(-row)

输出:

  Column1 Column2 Column3 Column4
1   blah1   blah2   blah3   blah4
2   blah1   blah2   blah3   blah4
3   blah1   blah2   blah3   blah4

【讨论】:

  • 非常感谢细节,帮助我学习!不幸的是,我在尝试在步骤 1 下运行代码时遇到错误)矩阵中的错误(unlist(pieces),ncol = n,byrow = TRUE):'data' 必须是向量类型,是 'NULL'跨度>
  • 知道我可以用什么来解决这个问题吗?好像不喜欢列名?
  • 当您使用问题中的测试数据(我在回答中使用的数据)时,您是否会收到该错误?如果是这样,那么这是单独函数的问题 --- 可能您加载了另一个库,该库具有干扰 tidyr 的单独函数的单独函数。你可以通过写tidyr::separate( 而不仅仅是separate( 来解决这个问题。如果您在测试数据上没有收到该错误,但您在自己的数据上,那么这是您的数据的问题。使用 strViewsummary 等函数探索您的数据,以确保所有数据对您来说都是正确的。
  • 另请注意,您通过管道发送到separate 的数据需要是data.frame。它不能是列表、矩阵等。您可以使用str 查看您的数据对象是什么类(除其他外)
  • 我已经检查了您的所有建议,并且一切似乎都已完成。我验证了 mydata 是一个 data.frame 并且列(TEST)是一个类型字符。也只是为了确保我添加了 tidyr::separate。这是我最新版本的代码: mydata %>% tidyr::separate(as.data.frame(rows, into=paste0("column", 1:4)), sep=";")
【解决方案2】:

这是一个基本的 r 尝试

#Example data provided
data <- data.frame(
 string=c(
  "Column1 = blah1; Column2 = blah2; Column3 = blah3; Column4 = blah4",
  "Column1 = blah1; Column2 = blah2; Column3 = blah3; Column4 = blah4"))

#Modulo function for odd and even numbers
odd <- function(x) x%%2 != 0 
even <- function(x) x%%2 == 0 

#split string based on condition and remove all xtra whitespace
s <- gsub("[[:space:]]", "", unlist(strsplit(as.character(data$string), '= |;')))

#bind the data into a df no factors
data <- data.frame(rbind(unique(s[even(1:length(s))]),
                   unique(s[even(1:length(s))])),
                   stringsAsFactors=F)
#rename column names exctrating the odd vector numbers from s
colnames(data) <- unique(s[odd(1:length(s))])

data

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2016-12-21
  • 2021-01-14
  • 2020-01-23
  • 1970-01-01
  • 2016-01-22
  • 1970-01-01
  • 2017-06-12
相关资源
最近更新 更多