使用R dplyr整理数据帧

时间:2019-07-29 17:18:42

标签: r xml dplyr tidyverse

我的数据框df如下:

        Value
X.Y.Z   10
X.Y.K   20
X.Y.W   30
X.Y.Z.1 20
X.Y.K.1 5
X.Y.W.1 30
X.Y.Z.2 3
X.Y.K.2 23
X.Y.W.2 44

我正在尝试使用行名称的第3个字符来取消命名,例如:

enter image description here

因此,行名现在是行的最后一个字符(在点之后)。 我知道这可以和dplyr一起使用,我已经尝试过gatherspread,但是没有运气,有人可以帮忙吗?

谢谢!

编辑: 这是上面文本中的数据,我:

structure(list(..1 = c("X.Y.Z", "X.Y.K", "X.Y.W", "X.Y.Z.1", 
"X.Y.K.1", "X.Y.W.1", "X.Y.Z.2", "X.Y.K.2", "X.Y.W.2"), Value = c(10, 
20, 30, 20, 5, 30, 3, 23, 44)), class = "data.frame", row.names = c(NA, 
-9L))

2 个答案:

答案 0 :(得分:5)

似乎适用于OP的解决方案:

library(dplyr)
library(tibble)
library(tidyr)

df1 %>% 
    rownames_to_column %>% 
    transmute(mycols = gsub('^.*\\.', '', gsub('.[[:digit:]]+', '', rowname)),
              myrows = regmatches(rowname, gregexpr('[0-9]+',rowname)),
              value = Value) %>% 
    spread(key=mycols, value=value)
  #   myrows  K  W  Z
  # 1        20 30 10
  # 2      1  5 30 20
  # 3      2 23 44  3


我的答案的第一个版本:

library(dplyr)
library(tidyr)

df1 %>% 
  mutate(mycols = substr(gsub('.[[:digit:]]+', '', rownames(.)), 5, 5),
         myrows = as.integer(as.factor(substr(rownames(.),7,7)))-1) %>% 
  spread(key=mycols, value=Value)

#>   myrows  K  W  Z
#> 1      0 20 30 10
#> 2      1  5 30 20
#> 3      2 23 44  3

数据:

df1 <- structure(list(Value = c(10, 20, 30, 20, 5, 30, 3, 23, 44)), 
                 row.names = c("X.Y.Z", "X.Y.K", "X.Y.W", "X.Y.Z.1", 
                               "X.Y.K.1", "X.Y.W.1", "X.Y.Z.2", "X.Y.K.2", "X.Y.W.2"), 
                 class = "data.frame")


更新I:

正如我在评论中所说,由于$..1列导致dplyr出现问题,我们需要清除数据。这是使用问题中提供的确切数据的解决方案:

df1 <- structure(list(..1 = c("X.Y.Z", "X.Y.K", "X.Y.W", "X.Y.Z.1", 
                              "X.Y.K.1", "X.Y.W.1", "X.Y.Z.2", "X.Y.K.2", "X.Y.W.2"), 
                      Value = c(10, 20, 30, 20, 5, 30, 3, 23, 44)), 
                      class = "data.frame", row.names = c(NA, -9L))

library(dplyr)
library(janitor)
library(tidyr)

clean_names(df1) %>% 
  mutate(mycols = substr(gsub('.[[:digit:]]+', '', x1), 5, 5),
         myrows = as.integer(as.factor(substr(x1,7,7)))-1) %>% 
  select(-x1) %>% 
  spread(key=mycols, value=value)

#>   myrows  K  W  Z
#> 1      0 20 30 10
#> 2      1  5 30 20
#> 3      2 23 44  3

reprex package(v0.3.0)于2019-07-29创建



更新II:

结合更多方法来查看它们是否适用于OP的数据集。 (没有一个可复制的示例,即使不是不可能,也很难解决;因此,这是我最后的努力。)

library(dplyr)
library(tibble)
library(tidyr)
df1 %>% 
  rownames_to_column %>% 
  mutate(mycols = gsub('.[[:digit:]]+', '', rowname),
         myrows = regmatches(rowname, gregexpr('[0-9]+',rowname))) %>% 
  select(-rowname) %>% 
  spread(key=mycols, value=Value)

df1 %>% 
  rownames_to_column %>% 
  separate(rowname,sep = "\\.", into = c("A1","B2","C3", "D4")) %>% 
  select(-A1,-B2) %>% 
  spread(key=C3, value=Value)

答案 1 :(得分:1)

尝试一下:

library(dplyr) # and tibble is needed, too
library(tidyr)
df %>%
  tibble::rownames_to_column() %>%
  mutate(
    type = gsub("(^X\\.Y\\.|\\.[0-9]$)", "", rowname),
    num = gsub("\\D", "", rowname)
  ) %>%
  select(-rowname) %>%
  spread(type, Value)
#   num  K  W  Z
# 1     20 30 10
# 2   1  5 30 20
# 3   2 23 44  3

顺便说一句,从您的问题来看,看来您的rownames是正确的,但是您的structure将它们包括在名为..1的列中。我认为这可能是试图将数据输入到您的问题中的一种人工产物,因此我将其删除。

df <- structure(list(..1 = c("X.Y.Z", "X.Y.K", "X.Y.W", "X.Y.Z.1", 
"X.Y.K.1", "X.Y.W.1", "X.Y.Z.2", "X.Y.K.2", "X.Y.W.2"), Value = c(10, 
20, 30, 20, 5, 30, 3, 23, 44)), class = "data.frame", row.names = c(NA, -9L))
rownames(df) <- x$..1
df$..1 <- NULL

如果情况并非如此,则可以删除对tibble::rownames_to_column()的呼叫。但是,在dplyr链中放置..1不好(Error: Column 1 must not have names of the form ... or ..j.),因此无论如何都需要重命名。