首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何根据数据类型在两列之间交换数据?[R]

如何根据数据类型在两列之间交换数据?[R]
EN

Stack Overflow用户
提问于 2020-07-03 03:37:02
回答 3查看 165关注 0票数 1

ds <- read.csv(file="~/Desktop/abalone.csv)

代码语言:javascript
复制
Sex  Length
 M     12.1
 F     11.2
12.1    F
 I     11.2
12.1   11.2
11.2    I

数据集包含两个列,分别是性别和长度。性列包含三个值,即"F“(女性)、"M”(男性)和"I“(婴儿)。数据集已被修改,有几个问题我需要解决。我需要解决以下问题

question)

  • Invalid values(solved)

  1. 错误值(需要帮助)

我解决错域值的想法是根据长度的值在两列之间交换数据。假设长度中的值是"F“、"M”和"I",则将数据与性别交换。我真的不知道如何根据长度的值在这两列之间交换数据。

代码语言:javascript
复制
swap_if <-function (ds$Sex, ds$Length, missing = NA){
  a <- ds$Length == "M"
  b <- ds$Length == "F"
  c <- ds$Length == "I"}

swap_if(ds$Sex, ds$Length)

但这行不通。有人能帮我做这个吗。非常感谢

之后,我需要删除无效的值。第五行第一列的值无效,因为“性”的值必须为“F”、“M”和“I”。

代码语言:javascript
复制
#remove wrong format /invalid data in sex column
ds <- ds[!str_detect(ds$Sex, '([0-9])'), ]
ds$Sex <- as.factor(ds$Sex)

^此代码可以删除格式值无效/错误的行。

EN

回答 3

Stack Overflow用户

发布于 2020-07-03 03:52:32

尽管我建议(修复问题的根源),但这里有一个尝试恢复的方法。

代码语言:javascript
复制
column <- grepl("^[.0-9]+$", dat[,1])
column
# [1] FALSE FALSE FALSE  TRUE FALSE  TRUE  TRUE FALSE
dat2 <- data.frame(Sex = dat[cbind(seq_len(nrow(dat)),1+column)], Length = dat[cbind(seq_len(nrow(dat)),2-column)])
dat2$Length <- as.numeric(dat2$Length)
dat2
#   Sex Length
# 1   M   12.2
# 2   F   14.1
# 3   M   14.6
# 4   F    9.0
# 5   L   12.1
# 6   M   10.1
# 7   F   11.0
# 8   M   11.9

一种潮流选择:

代码语言:javascript
复制
library(dplyr)
dat %>%
  mutate(
    swap    = grepl("[^.[:digit:]]", Length), 
    Length2 = if_else(swap, Sex, Length), 
    Sex2    = if_else(swap, Length, Sex)
  ) %>%
  transmute(
    Sex    = Sex2, 
    Length = as.numeric(Length2)
  )
#   Sex Length
# 1   M   12.2
# 2   F   14.1
# 3   M   14.6
# 4   F    9.0
# 5   L   12.1
# 6   M   10.1
# 7   F   11.0
# 8   M   11.9

数据:

代码语言:javascript
复制
dat <- structure(list(Sex = c("M", "F", "M", "9", "L", "10.1", "11", 
"M"), Length = c("12.2", "14.1", "14.6", "F", "12.1", "M", "F", 
"11.9")), class = "data.frame", row.names = c(NA, -8L))
票数 1
EN

Stack Overflow用户

发布于 2020-07-03 04:28:39

下面是另一个与tidyverse一起工作的解决方案。它创建一个小助手列,该列将在末尾被删除。

代码语言:javascript
复制
library(tidyverse)

# create the inverse of `%in%`
`%!in%` = Negate(`%in%`)

df %>% 
  # create a helper column, will be deleted
  mutate(help = Sex) %>% 
  mutate(Sex = case_when(
    Sex  %!in% c('L', 'M', 'F') ~ Length,
    TRUE ~ Sex
  )) %>% 
  mutate(Length = case_when(
    Length %in% c('L', 'M', 'F') ~ help,
    TRUE ~ Length
  )) %>% 
  # delete helper column
  select(-help)
#>   Sex Length
#> 1   M   12.2
#> 2   F   14.1
#> 3   M   14.6
#> 4   F      9
#> 5   L   12.1
#> 6   M   10.1
#> 7   F     11
#> 8   M   11.9
票数 1
EN

Stack Overflow用户

发布于 2020-07-03 03:56:20

您可以使用if -然后设置一个for循环来检查字符变量是否可以安全地转换为数字。如果是这样的话,它属于length

代码语言:javascript
复制
sex = c('M','F', 'M', 9, 'L', 10.1, 11, 'M')
length = c(12.2, 14.1, 14.6, 'F', 12.1, 'M', 'F', 11.9)

df = data.frame(sex, length)
str(df)

df$sex.c = 0
df$length.c = 0

for (i in 1:length(df$sex)){
  if (!is.na(as.numeric(df$sex[i]))){
    df$sex.c[i] = df$length[i]
    df$length.c[i] = df$sex[i]
  } else {
    df$sex.c[i] = df$sex[i]
    df$length.c[i] = df$length[i]
  }
}

df$sex = df$sex.c
df$length = df$length.c

df = df[,1:2]

请注意,这将创建一个NAs introduced by coercion警告。如果这让您感到困扰,那么您可以通过更改for循环来抑制它们,如下所示:

代码语言:javascript
复制
for (i in 1:length(df$sex)){
  if (suppressWarnings(!is.na(as.numeric(df$sex[i])))){
    df$sex.c[i] = df$length[i]
    df$length.c[i] = df$sex[i]
  } else {
    df$sex.c[i] = df$sex[i]
    df$length.c[i] = df$length[i]
  }
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62708141

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档