【问题标题】:Split a single column into multiple columns based on Rows根据 Rows 将单列拆分为多列
【发布时间】:2015-10-20 11:26:02
【问题描述】:

我在 R 中有一个数据集,它由一列组成,其中包含我理想情况下希望在多列中出现的变量。单列dataframe的结构是这样的。

A1
200
250
Brand x 
A2
400
300
Brand x
A4
100
320
Brand x2

我想以这样的方式拆分此列,使其以这样的多列框架结束(“|”纯粹表示列分隔符):

A1 | 200 | 250 | Brand x  
A2 | 400 | 300 | Brand x1
A4 | 100 | 320 | Brand x2

我怎么能这样做?水平数据中最多有一个序列 - 例如:4个变量 - A1,200, 250,Brand x。天真的等价物是在 Excel 中复制和转置粘贴,但要使用 4 个值的预定义序列。谁能帮我解决这个问题?

【问题讨论】:

  • 总是4个值吗?

标签: r


【解决方案1】:

我会这样做:

df2 <- as.data.frame(matrix(df1[,1], byrow=TRUE, ncol = 4))

或者,等效地:

df2 <- as.data.frame(t(matrix(df1[,1],nrow = 4)))

在这两种情况下,这都会产生预期的结果:

#> df2
#  V1  V2  V3       V4
#1 A1 200 250  Brand x
#2 A2 400 300  Brand x
#3 A4 100 320 Brand x2

数据

df1 <-read.table(text="A1
                       200
                       250
                       'Brand x' 
                       A2
                       400
                       300
                      'Brand x'
                       A4
                       100
                       320
                       'Brand x2'", header=FALSE)

【讨论】:

  • 和 Alexes 的回答一样,不是吗?
  • 也许,我没有检查。它已经改变了很多次,以至于我迷失了方向。不过这个看起来有点短。
  • @DavidArenburg 我在这里看不到任何as.characterstringAsFactorstype.convertlapply。所以我会说它是不同的。结果除外。
  • 对不起。我一开始就在某个地方漏掉了,并提前发布了答案。
  • 我不会说结果是一样的。试试str(df2)。所有变量都应该是因素。当你开始使用 R 时,有时会更容易一步一步地做事情以了解正在发生的事情(至少在我作为初学者的经验中
【解决方案2】:

这不是一个优雅的解决方案,但应该可以。

一些解释:

前两行应该只提供通常通过读取数据获得的数据帧。

如果列中有字符串,R 会将该列转换为因子变量。出于这个原因,我在第 3 行将其转换回字符向量。

使用矩阵,您可以将这个向量重新排列成您想要的形状,然后您可以将其转换回数据框(设置stringAsFactors=FALSE 以防止所有内容都转换为默认值)。

但是,现在所有的变量都是字符变量。因此,您需要对变量进行适当的编码。

dat<-c("A1",200,250,"Brand x" ,"A2",400,0300, "Brand x", "A4",100,  320,"Brand x2")
dat<-data.frame(dat)
dat<-as.character(dat[,1])
dat<-matrix(dat, ncol = 4, byrow=TRUE)
dat<-data.frame(dat, stringsAsFactors = FALSE)

dat[] <- lapply(dat, type.convert)

> str(dat)
'data.frame':   3 obs. of  4 variables:
 $ X1: Factor w/ 3 levels "A1","A2","A4": 1 2 3
 $ X2: int  200 400 100
 $ X3: int  250 300 320
 $ X4: Factor w/ 2 levels "Brand x","Brand x2": 1 1 2

> dat
     X1  X2  X3       X4
 1 A1 200 250  Brand x
 2 A2 400 300  Brand x
 3 A4 100 320 Brand x2

【讨论】:

  • 使用dat[] &lt;- lapply(dat, type.convert)而不是手动做as.numeric等。你还没有弄清楚如何识别列数。
  • 您没有正确复制它。您需要在dat 的末尾添加[],否则您将创建一个列表而不是data.frame
  • 我没认出来,但它是固定的。
【解决方案3】:

这里只是一个提示 - 如果序列总是重复(即是确定性的),您可以读取一个向量并更改维度,例如:

data <- c("A1","200","250","Brand x","A2","400","300","Brand x","A4","100","320","Brand x2")
dim(data) <- c(4,3)
data <- t(data) # transpose
class(data)
data.df <- as.data.frame(data)
class (data.df)

这会将数据的暗淡更改为矩阵(由于内部向量和矩阵存储相同,因此维度不同)。

执行时会打印

> class(data)
[1] "matrix"
> class (data.df)
[1] "data.frame"

然后data.df 是一个 data.frame 对象,因此您可以在处理数据之前对数据执行任何您需要执行的操作(例如,将列更改为数字/字符/等)。

【讨论】:

    【解决方案4】:

    如果它始终是 4 个值,则下面的循环为我完成了工作:

    df <- read.csv("df.csv", sep = ";", header = FALSE)
    
    
    new.df <- data.frame()
    j <- 1
    i <- 1
    while(i < length(df[,1])-1){
    
        temp.df <- data.frame()
    
        temp.df[j,1] <- df[i,1]
        temp.df[j,2] <- df[i + 1, 1]
        temp.df[j,3] <- df[i + 2, 1]
        temp.df[j,3] <- df[i + 3, 1]
    
        new.df <- rbind(new.df, temp.df)
    
        j <- j + 1
        i <- i + 4
    }
    na.omit(new.df)
    

    它没有完全优化,但可以完成工作!希望它对你有用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-09-12
      • 1970-01-01
      • 1970-01-01
      • 2023-02-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多