将一列的数据帧转换为R中的多列

时间:2020-02-19 17:29:31

标签: r dataframe transform reshape transpose

当前,我的数据框由1列和2326行组成。我想将数据框转换为11行。更具体地说,我当前的数据框看起来像

John Doe
7
45
42
978
3
6
8
9
0
11
Sally Jenkins
2

我希望数据框看起来像这样:

John Doe        7  45  42  978  3  6  8  9  0  11 
Sally Jenkins   2  

每个人都是一行,然后他们的统计信息都在该行的一个单独列中。某些人缺少统计信息,因此我无法根据每个人的姓名之间的行数进行区分。

我尝试使用t()reshape(transform())。您对下一步去有什么建议吗?

2 个答案:

答案 0 :(得分:1)

1)一种方法是根据字母的存在来创建分组变量,summarise通过创建list输出并使用unnest_wider进行更改list到一组新列

library(dplyr)
library(tidyr)
library(stringr)
df1  %>%
      group_by(grp = cumsum(str_detect(col1, "[A-Za-z]"))) %>%
      group_by(coln = first(col1), .add = TRUE) %>%
      slice(-1) %>%
      summarise(out = list(as.list(as.numeric(col1))))  %>%
      unnest_wider(c(out)) %>%
      ungroup %>%
      select(-grp) %>%
      rename_at(-1, ~ str_c('new_col', seq_along(.)))
# A tibble: 2 x 11
#  coln          new_col1 new_col2 new_col3 new_col4 new_col5 new_col6 new_col7 new_col8 new_col9 new_col10
#  <chr>            <dbl>    <dbl>    <dbl>    <dbl>    <dbl>    <dbl>    <dbl>    <dbl>    <dbl>     <dbl>
#1 John Doe             7       45       42      978        3        6        8        9        0        11
#2 Sally Jenkins        2       NA       NA       NA       NA       NA       NA       NA       NA        NA

2)或使用base R(未使用软件包)

grp <- with(df1, ave(col1, cumsum(grepl('[A-Za-z]', col1)), 
     FUN = function(x) x[1]))
aggregate(values ~ ind, stack(split(as.numeric(df1$col1[duplicated(grp)]), 
           grp[duplicated(grp)])),  FUN = I)
#            ind                            values
#1      John Doe 7, 45, 42, 978, 3, 6, 8, 9, 0, 11
#2 Sally Jenkins                                 2

数据

df1 <- structure(list(col1 = c("John Doe", "7", "45", "42", "978", "3", 
"6", "8", "9", "0", "11", "Sally Jenkins", "2")), class = "data.frame", 
row.names = c(NA, 
-13L))

答案 1 :(得分:0)

使用末尾注释中可重复定义的DF,确保DF[[1]]是字符。然后使用grep创建一个逻辑变量g,每个输入行有一个元素,每个标题为TRUE,否则为FALSE。然后删除标题并使用setNames将其拆分以设置结果列表的名称。最后,将每个列表组件转换为数字ts系列,因为即使它们具有不同的长度,这些系列也可以绑定。现在cbind将它们放在一起并转置。不使用任何软件包。

DF[[1]] <- as.character(DF[[1]]) 
g <- grepl("\\D", DF[[1]])
s <- setNames(split(DF[[1]][!g], cumsum(g)[!g]), DF[[1]][g])
t(do.call("cbind", lapply(s, function(x) ts(as.numeric(x)))))

给予:

              [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
John Doe         7   45   42  978    3    6    8    9    0    11
Sally Jenkins    2   NA   NA   NA   NA   NA   NA   NA   NA    NA

注意

可重复输入的形式假定为:

Lines <- "John Doe
7
45
42
978
3
6
8
9
0
11
Sally Jenkins
2"
DF <- read.table(text = Lines, as.is = TRUE, sep = ";")
相关问题