【问题标题】:Need an efficient way to change factor values from one column of a data frame to another columns需要一种有效的方法将因子值从数据框的一列更改为另一列
【发布时间】:2020-05-23 01:47:45
【问题描述】:

我目前正在处理data.frame 中的分类数据,其中两列是类型因子。它总共有大约 9000 行,有 40 多个级别。目前,我首先将这些列更改为字符,因为当我尝试使用它们的因子形式更改它们时,我得到了 NA 值。将这些列更改为字符后,我能够更改它们,然后将列的类型更改回因子。

这是我的方法代码:

library(dplyr)

#model data frame
df <- data.frame(A= as.factor(c("Jerry", "Kelly","Kelly", "Lion", "Zebra", "Bear", "Kelly")), 
                 B= as.factor(c("Eats", "Jumps", "Roasts", "Roars", "Runs", "Sleeps", "Jumps")))
glimpse(df)

#Observations: 7
#Variables: 2
#$ A <fct> Jerry, Kelly, Kelly, Lion, Zebra, Bear, Kelly
#$ B <fct> Eats, Jumps, Roasts, Roars, Runs, Sleeps, Jumps

#select those factor columns and change their type
df[c("A","B")] <- lapply(df[ c("A", "B")], as.character)

glimpse(df)
#Variables: 2
#$ A <chr> "Jerry", "Kelly", "Kelly", "Lion", "Zebra", "Bear", "K...
#$ B <chr> "Eats", "Jumps", "Roasts", "Roars", "Runs", "Sleeps", ...

#now I want to change Kelly's actions for example                           
df<- within(df,B[A %in% c("Kelly")] <- "CHANGED")
print(df)

#      A       B
#1 Jerry    Eats
#2 Kelly CHANGED
#3 Kelly CHANGED
#4  Lion   Roars
#5 Zebra    Runs
#6  Bear  Sleeps
#7 Kelly CHANGED

#Then I change it back
df[c("A","B")] <- lapply(df[ c("A", "B")], as.factor)

glimpse(df)
#Observations: 7
#Variables: 2
#$ A <fct> Jerry, Kelly, Kelly, Lion, Zebra, Bear, Kelly
#$ B <fct> Eats, CHANGED, CHANGED, Roars, Runs, Sleeps, CHANGED

问题是,从我正在使用的数据来看,字符方式方法不是一个好方法。有没有一种替代方法可以让我以一种简洁的方式将因子/水平转换为因子/水平?用独特的功能测试,使字符列表现得像关卡,但我确信我缺少一些知识。

【问题讨论】:

  • 作为替代,为什么不将它们作为字符读入然后更新它们,以便您只需将它们设置为因子一次
  • 感谢您的回复。我正在处理别人的脚本文件。所以我不知道我是否应该去那里更改他的代码。我的任务是分类,以及完成数据加载和清理的部分。
  • 还不错;但您可以将stringsAsFactors=FALSE 添加到数据加载部分
  • 是的,你绝对正确。让我再深入研究一下他的代码,我不想在我这样做之后搞砸一些事情。你知道,我告诉那个**就这样做,但他不听。

标签: r dataframe data-cleaning


【解决方案1】:

我们可以使用fct_collapse,它返回一个factor和新的levels

library(dplyr)
library(forcats)
library(magrittr)
df %<>%
    mutate(B = fct_collapse(B, CHANGED = as.character(B)[A== "Kelly"]))

glimpse(df)
#Rows: 7
#Columns: 2
#$ A <fct> Jerry, Kelly, Kelly, Lion, Zebra, Bear, Kelly
#$ B <fct> Eats, CHANGED, CHANGED, Roars, Runs, Sleeps, CHANGED

【讨论】:

  • @ToadPitt 将== 更改为%in%,因为== 用于逐元素比较。如果== rhs 上的向量长度不同,它会回收(长度为 1 很好,但 > 1 时,它只是第一行与 Jerry 比较,第二行与 Kelly 比较,第三行与 Jerry 比较,等等。而是使用%in%
  • 搞定老板。非常感谢阿克伦!欣赏它。
  • @ToadPitt。我无法重现df &lt;- data.frame(A= as.factor(c("Water Pipe Leaks/Spills", "Building (Abandoned/Damaged)","Kelly", "Water Pipe Leaks/Spills", "Zebra", "Grass (Overgrown)", "Kelly")), B= as.factor(c("Eats", "Jumps", "Roasts", "Roars", "Runs", "Sleeps", "Jumps")));df %&lt;&gt;% mutate(B = fct_collapse(B, CHANGED = as.character(B)[A == "Water Pipe Leaks/Spills"]));
  • @ToadPitt 为了比较,我将它分配给不同的对象kd1 &lt;- kd %&gt;% mutate(B = fct_collapse(B, CHANGED = as.character(B)[A == "Water Pipe Leaks/Spills"])); levels(kd1$B)# [1] "Public Services" "CHANGED" "Health and Public Safety" "Transportation"
  • @ToadPitt 如果您检查as.character(kd$B[kd$A == "Water Pipe Leaks/Spills"]) [1] "Neighborhoods" "Neighborhoods" "Neighborhoods" "Neighborhoods" "Neighborhoods" "Neighborhoods" "Neighborhoods" [8] "Neighborhoods" "Neighborhoods" "Neighborhoods" "Neighborhoods" "Neighborhoods" "Neighborhoods" "Neighborhoods" [15] "Neighborhoods" "Neighborhoods" "Neighborhoods" "Neighborhoods" 邻里的任何地方,它将更改为“已更改”。它也可以在其他行中,即。 sum(kd$B == "Neighborhoods", na.rm = TRUE) [1] 4315
【解决方案2】:

这不是也行吗?

df <- df %>%
  mutate(B = ifelse(A == 'Kelly', 'CHANGED', B))

【讨论】:

  • 嗨亚当,这也有效。但是,我选择 Akruns 响应作为答案,因为他是第一个。非常感谢您的帮助,非常感谢。
  • 别担心!如果您想对因素进行更改,Akrun 的答案可能会更好。
【解决方案3】:

如果您想在不将列转换为字符的情况下执行此操作。一种方法是添加数据中不存在的因子水平 ("CHANGED"),然后直接分配值。

levels(df$B) <- c(levels(df$B), "CHANGED")
df$B[df$A == "Kelly"] <- "CHANGED"
df

#      A       B
#1 Jerry    Eats
#2 Kelly CHANGED
#3 Kelly CHANGED
#4  Lion   Roars
#5 Zebra    Runs
#6  Bear  Sleeps
#7 Kelly CHANGED

数据

df <- data.frame(A= as.factor(c("Jerry", "Kelly","Kelly", "Lion", "Zebra", 
                    "Bear", "Kelly")), 
                 B= as.factor(c("Eats", "Jumps", "Roasts", "Roars", "Runs",
                    "Sleeps", "Jumps")))

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-11-12
    • 1970-01-01
    • 2020-09-22
    • 1970-01-01
    • 2021-10-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多