【问题标题】:How to create a new variable from (9) repeated values in R? Do I need loops?如何从 R 中的 (9) 个重复值创建一个新变量?我需要循环吗?
【发布时间】:2018-06-20 20:00:30
【问题描述】:

首先,对于标题含糊不清,我深表歉意。我有一个数据集,其中包含对某个变量 X 编码为 01 的二分值。v001 是主题标识符,从 v1pc10le8v9pc10le8 的值是九个中每个 X 的值访问。此外,firstpc10lastpc10 分别表示 X 的第一个(基线)和最后一个测量值。

      v001 firstpc10 lastpc10 v1pc10le8 v2pc10le8 v3pc10le8 v4pc10le8 v5pc10le8 v6pc10le8 v7pc10le8 v8pc10le8 v9pc10le8
1473 28084         0        0         0      <NA>         0      <NA>      <NA>         0         0      <NA>      <NA>
1474 28089         0        0      <NA>      <NA>      <NA>         0      <NA>         0      <NA>      <NA>      <NA>
1475 28102         0        1      <NA>      <NA>         0         0         0         0         1      <NA>      <NA>
1476 28103         0        1      <NA>      <NA>      <NA>         0         0         0         0         1         1
1477 28119         0        0      <NA>      <NA>      <NA>         0      <NA>         0         0         0      <NA>
1478 28184         0        1      <NA>      <NA>         0      <NA>      <NA>         0      <NA>      <NA>         1
1479 28202         1        1      <NA>      <NA>         1      <NA>         0         0         0         1         1
1480 28211         0        0         0      <NA>         0         0      <NA>      <NA>      <NA>      <NA>      <NA>
1481 28212         0        1         0      <NA>      <NA>         1      <NA>      <NA>      <NA>      <NA>      <NA>
1482 28213         0        0      <NA>      <NA>         0      <NA>      <NA>         0      <NA>      <NA>      <NA>
1483 28214         0        0      <NA>      <NA>      <NA>         0         0         0      <NA>         1         0
1484 28215         0        0      <NA>      <NA>      <NA>         0      <NA>         0         0         0         0
1485 28232         0        1      <NA>      <NA>         0      <NA>         0         1      <NA>      <NA>      <NA>
1486 28244         1        1         1      <NA>      <NA>      <NA>         0         0         0         0         1
1487 28258         0        1      <NA>      <NA>      <NA>         0      <NA>         0         1      <NA>         1
1488 28281         0        1      <NA>      <NA>      <NA>         0         0         0         1      <NA>      <NA>
1489 28303         0        0         0      <NA>      <NA>      <NA>      <NA>         0         0         0      <NA>
1490 28337         0        1      <NA>      <NA>         0      <NA>      <NA>         0      <NA>         1      <NA>
1491 28355         1        1      <NA>      <NA>         1      <NA>         0      <NA>         0         1      <NA>
1492 29983         0        0      <NA>      <NA>      <NA>         0         0      <NA>         0         0         0

我想忽略所有NA 并计算一个名为“change”的新变量,它具有以下值:

1 - 如果受试者在基线时为 0 并且始终保持为 0

2 - 如果受试者在基线时为 1 并且始终保持为 1

3 - 如果受试者在基线时为 1 并更改为 0(并且始终保持为 0)

4 - 如果受试者在基线时为 0 并更改为 1(并且始终保持为 1)

5 - 如果受试者在 0 和 1 的值之间波动而没有趋势(例如受试者 #28214) - 这些受试者不属于上述 4 个类别

这是我希望看到的输出:

      v001   change
1473 28084      1
1474 28089      1 
1475 28102      4
1476 28103      4
1477 28119      1
1478 28184      4    
1479 28202      5
1480 28211      1
1481 28212      4
1482 28213      1
1483 28214      5
1484 28215      1
1485 28232      4
1486 28244      5
1487 28258      4
1488 28281      4
1489 28303      1
1490 28337      4
1491 28355      5
1492 29983      1 

我尝试使用 SPSS 和 R 来做到这一点,但我遇到了巨大的困难,我将非常感谢任何帮助。 (我在下面包含了来自 R 的 dput 输出)。

谢谢!

structure(list(v001 = c(28084, 28089, 28102, 28103, 28119, 28184, 
28202, 28211, 28212, 28213, 28214, 28215, 28232, 28244, 28258, 
28281, 28303, 28337, 28355, 29983), firstpc10 = c(0, 0, 0, 0, 
0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0), lastpc10 = c(0, 
0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0), v1pc10le8 = c(0, 
NA, NA, NA, NA, NA, NA, 0, 0, NA, NA, NA, NA, 1, NA, NA, 0, NA, 
NA, NA), v2pc10le8 = c(NA_real_, NA_real_, NA_real_, NA_real_, 
NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, 
NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, 
NA_real_, NA_real_), v3pc10le8 = c(0, NA, 0, NA, NA, 0, 1, 0, 
NA, 0, NA, NA, 0, NA, NA, NA, NA, 0, 1, NA), v4pc10le8 = c(NA, 
0, 0, 0, 0, NA, NA, 0, 1, NA, 0, 0, NA, NA, 0, 0, NA, NA, NA, 
0), v5pc10le8 = c(NA, NA, 0, 0, NA, NA, 0, NA, NA, NA, 0, NA, 
0, 0, NA, 0, NA, NA, 0, 0), v6pc10le8 = c(0, 0, 0, 0, 0, 0, 0, 
NA, NA, 0, 0, 0, 1, 0, 0, 0, 0, 0, NA, NA), v7pc10le8 = c(0, 
NA, 1, 0, 0, NA, 0, NA, NA, NA, NA, 0, NA, 0, 1, 1, 0, NA, 0, 
0), v8pc10le8 = c(NA, NA, NA, 1, 0, NA, 1, NA, NA, NA, 1, 0, 
NA, 0, NA, NA, 0, 1, 1, 0), v9pc10le8 = c(NA, NA, NA, 1, NA, 
1, 1, NA, NA, NA, 0, 0, NA, 1, 1, NA, NA, NA, NA, 0)), .Names = c("v001", 
"firstpc10", "lastpc10", "v1pc10le8", "v2pc10le8", "v3pc10le8", 
"v4pc10le8", "v5pc10le8", "v6pc10le8", "v7pc10le8", "v8pc10le8", 
"v9pc10le8"), row.names = 1473:1492, class = "data.frame")

【问题讨论】:

  • 欢迎来到 Stack Overflow。感谢您添加数据的dput。添加确切的预期输出也很有帮助。
  • @Deena 谢谢你的评论!我已经更新了问题并添加了我希望看到的输出。
  • 第四行的结果怎么是1?
  • 那应该是4,我已经更正了。谢谢!

标签: r loops variables if-statement


【解决方案1】:

@qdread 的解决方案在紧凑和整洁方面非常出色。除了这个伟大的方法之外,我想发布一个解决方案来演示如何以一种实用的方式解决这些问题。
.

第一步是确定应该用作基础的列和访问量,这基本上是直截了当的:

library(magrittr)

# Define the columns to be used 
col.visits = colnames(df)[4:ncol(df)] # Visits are represented from column 4 on
col.baseline = "firstpc10"
col.final = "lastpc10"

第二步是考虑如何定义“始终保持 0/1”:

# Define unit functions 
single_change_to_1 = function(numeric_array){
  positive_change = (diff(numeric_array) == 1)  # True if 0 -> 1 change occured
  return(sum(positive_change, na.rm = T) == 1)  # Return True if only 1 change occured 
}

single_change_to_0 = function(numeric_array){
  negative_change = (diff(numeric_array) == -1)  # True if 1 -> 0 change occured
  return(sum(negative_change, na.rm = T) == 1)   # Return True if only 1 change occured 
}

第三步是将您的条件放在一个函数中:

calculate_change = function(patientInfo){
  # Extract data 
  patient.base = patientInfo[[col.baseline]]
  patient.visits = patientInfo[col.visits] %>% as.numeric %>% .[!is.na(.)] # Turn to vector, and Discard NAs 

  # Apply if-else
  if(patient.base == 0 && all(patient.visits == 0)) return(1)
  if(patient.base == 1 && all(patient.visits == 1)) return(2)                                         

  if(patient.base == 1 && single_change_to_0(patient.visits) && !single_change_to_1(patient.visits)) return(3)                                         
  if(patient.base == 0 && single_change_to_1(patient.visits) && !single_change_to_0(patient.visits)) return(4)   

  # If the entry didnt match any of the previous conditions, return 5
  return(5)
}

最后,对每一行应用更改函数:

df[["change"]] = apply(df, 1, calculate_change)
df[["change"]]
# [1] 1 1 4 4 1 4 5 1 4 1 5 1 4 5 4 4 1 4 5 1

【讨论】:

  • 优雅的方法,它比我的教学目的要好得多!
【解决方案2】:

我定义了一个函数来输出 1-5,具体取决于起始条件和状态从 0 变为 1 的次数。我使用 dplyr 包中的 rowwise() 函数将该函数应用于数据框。我将输入数据框称为dat。我定义的函数使用diff() 来计算状态从 0 到 1 的“翻转”次数,并测试它是否只翻转一次,并根据基线状态返回 1、2、3、4 或 5 .

classify_change <- function(x) {
  baseline <- x$firstpc10
  visits <- na.omit(as.numeric(x[grepl('le8', names(x))]))

  # Count number of times the status flips from 0 to 1 between visits
  n_flips <- sum(diff(visits) != 0)

  answer <- 5

  if (baseline == 0 & n_flips == 0) answer <- 1
  if (baseline == 1 & n_flips == 0) answer <- 2
  if (baseline == 1 & n_flips == 1) answer <- 3
  if (baseline == 0 & n_flips == 1) answer <- 4

  return(data.frame(change = answer))

}

library(dplyr)

dat %>%
  rowwise %>%
  do(classify_change(.))

我注意到您的预期输出包含零,但类别的描述只有 1-5 个可能的结果。此函数为这些行返回 1。

【讨论】:

  • 非常感谢您的回答。是的,我的预期输出确实包含零,但这是一个错误,我已在问题中纠正了这一点。我将在整个数据集上尝试这个函数。
猜你喜欢
  • 2014-04-14
  • 2018-03-05
  • 1970-01-01
  • 2017-01-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-29
  • 1970-01-01
相关资源
最近更新 更多