【问题标题】:How do I clean this dataframe如何清理此数据框
【发布时间】:2016-12-02 12:20:26
【问题描述】:

我的数据具有以以下格式存储的变量:

             V2                             V3
1 Price :  33,990          Size : 16, 17 & 18.5"
2 Price :  30,830      Size : 13, 16, 18 & 19.5"
3 Price :  48,560             Sizes : 21 & 21.5"
4 Price :  33,790 Size : 17.5, 18.5, 19.5 & 21.5
5 Price :  37,990       Size : 17.5, 18.5 & 19.5
6 Price :  43,690      Size : 17.5, 18.5 & 19.5"

我需要的变量是PriceSize 等等。 R 中将这些原始数据转换为如下格式的最简洁方法是什么:

            Price        Size
1          33,990       16, 17 & 18.5"
2          30,830       13, 16, 18 & 19.5"
3          48,560       21 & 21.5"
4          33,790       17.5, 18.5, 19.5 & 21.5
5          37,990       17.5, 18.5 & 19.5
6          43,690       17.5, 18.5 & 19.5"

此外,第三行的变量名称拼写错误为Sizes,而不是Size。我该如何处理这个问题,因为还有其他变量有相同的错误?

编辑: 我不能使用特定于列的策略(例如使用gsub()),因为给定列中的变量不一致。具体来说,

                                           V20
1                        Grips : Bontrager SSR
2                  Headset : 1-1/8" threadless
3                                             
4          Brakeset : Tektro alloy linear-pull
5            Brakeset : HL 280 mechanical disc
6 Brakeset : Tektro M290 hydraulic disc brakes

V20 列有 3 个唯一变量,GripsHeadsetBrakeset 和一个空白。整洁的数据框应如下所示:

           Grips        Headset              Brakeset
1   Bontrager SSR       NA                   NA
2              NA       1-1/8" threadless    NA
3              NA       NA                   NA
4              NA       NA                   Tektro alloy linear-pull
5              NA       NA                   HL 280 mechanical disc
6              NA       NA                   Tektro M290 hydraulic disc brakes

这是一种过度简化,因为我假设 Brakeset 对前 3 行没有任何价值。这可能是也可能不是,因为值可能存储在不同的列中。如果特定行对给定变量没有值,则将使用 NA。我希望问题很清楚。

【问题讨论】:

  • tidyr 包中的分离()函数
  • 您可以删除“价格:”和“尺寸:”(尺寸是错字吗?),然后重命名列。您可能还想用“.”替换“,”。 gsub 可以在这里成为你的主力。
  • gsub() 很容易做到这一点。不需要任何包。
  • 如果价格和尺寸不一致,那么strsplit(x, split = ':')[[1]][2] 会起作用。
  • @GreenNoob 甚至 gsub() 都应该在这种情况下工作。 “。*”会照顾它。就像我的回答一样

标签: r data-cleaning


【解决方案1】:
library(tidyr)
# convert = T automatically converts to integer/numeric
df$Price <- separate(df, Price, into = c("x","y"), sep = ":", convert = T)[,2]
df$Size  <- separate(df, Size, into = c("x","y"), sep = ":")[,2]

# with gsub()
# irrespective of what is appearing before ":", gsub() shall take care of it
df$Price <- trimws(gsub(".*\\:", "",df$Price)) # this should work

# I'm using the below data to explain. This is obtained after using separate() once.
df1
          x                                  y
1    Grips                       Bontrager SSR
2    Grips                       Bontrager SSR
3  Headset                    1-1/8 threadless
4 Brakeset   Tektro M290 hydraulic disc brakes

# need to add a unique key to the data
> df1[["id"]] <- 1:nrow(df1)
> df1
          x                                  y id
1    Grips                       Bontrager SSR  1
2    Grips                       Bontrager SSR  2
3  Headset                    1-1/8 threadless  3
4 Brakeset   Tektro M290 hydraulic disc brakes  4

# using spread() from tidyr package
> spread(df1, x, y)
  id                          Brakeset          Grips           Headset 
1  1                               <NA>  Bontrager SSR              <NA>
2  2                               <NA>  Bontrager SSR              <NA>
3  3                               <NA>           <NA>  1-1/8 threadless
4  4  Tektro M290 hydraulic disc brakes           <NA>              <NA>

【讨论】:

  • 我有 97 个唯一变量。有一个更好的方法吗?另外,如何确保将值分配给正确的变量?例如,假设我在给定列中有一行的值为Size : 60,下一行的值为Headset : Threadless。我需要第一行中的 Size 变量等于 60,第二行中的 Size 变量等于 NA。
  • 知道了...我会根据我的理解更新我的答案
  • 谢谢。 id字段有什么用?此外,如果变量存储在不同的列中,传播是否有效?例如,假设“耳机”变量存储在第 10 行的 V19 列。但是,第 11 行的“耳机”变量存储在 V15 列。是否会捕获 Headset 的相应值?
  • 问题太宽泛了。如果没有您的数据样本,我无法发表评论。我已经给出了不同的选择。你绝对可以试一试,然后告诉我
  • 对您的问题有帮助吗?介意接受答案吗?
【解决方案2】:

一种可能的替代方法:

# create a list of the needed columnnames for the desired dataframe
nameslist <- lapply(mydf, function(x) unique(trimws(gsub('\\:.*', '', x[x != '']))))

# create a new dataframe with this list
mydf2 <- mydf[, rep(names(mydf), lengths(nameslist))]
names(mydf2) <- unlist(nameslist)

# create an array index of which values need to be included
idx <- mapply(function(x,y) grepl(x, y), x = names(mydf2), y = mydf2)

# replace the other values with 'NA'
mydf2[!idx] <- NA

# use gsub to remove everything before ':'
mydf2[] <- lapply(mydf2, function(x) trimws(gsub('.*\\:', '', x)))

给出:

   Price                    Size         Grips          Headset                          Brakeset
1 33,990           16, 17 & 18.5 Bontrager SSR             <NA>                              <NA>
2 30,830       13, 16, 18 & 19.5          <NA> 1-1/8 threadless                              <NA>
3 48,560               21 & 21.5          <NA>             <NA>                              <NA>
4 33,790 17.5, 18.5, 19.5 & 21.5          <NA>             <NA>          Tektro alloy linear-pull
5 37,990       17.5, 18.5 & 19.5          <NA>             <NA>            HL 280 mechanical disc
6 43,690       17.5, 18.5 & 19.5          <NA>             <NA> Tektro M290 hydraulic disc brakes

使用过的数据:

mydf <- structure(list(V2 = c("Price :  33,990", "Price :  30,830", "Price :  48,560", "Price :  33,790", "Price :  37,990", "Price :  43,690"), 
                       V3 = c("Size : 16, 17 & 18.5", "Size : 13, 16, 18 & 19.5", "Size : 21 & 21.5", "Size : 17.5, 18.5, 19.5 & 21.5", "Size : 17.5, 18.5 & 19.5", "Size : 17.5, 18.5 & 19.5"), 
                       V4 = c("Grips : Bontrager SSR", "Headset : 1-1/8 threadless", "", "Brakeset : Tektro alloy linear-pull", "Brakeset : HL 280 mechanical disc", "Brakeset : Tektro M290 hydraulic disc brakes")), 
                  .Names = c("V2", "V3", "V4"), class = "data.frame", row.names = c(NA, -6L))

【讨论】:

  • 非常感谢。我假设参数 lst 是 mapply 函数中的 names(mydf2) 。我希望我的理解是正确的。如何处理名单中的重复项?有没有办法将所有具有相同名称的变量组合成一个变量? (类似于行的聚合函数)
  • lst 确实与names(mydf2) 相同(忘记在我的代码的最后一次迭代中更改它);更新了我的答案
猜你喜欢
  • 2022-10-13
  • 1970-01-01
  • 2012-08-23
  • 1970-01-01
  • 1970-01-01
  • 2021-09-04
  • 2019-05-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多