【问题标题】:For loop to extract data scattered across multiple columns in another R dataframeFor循环提取分散在另一个R数据帧中多列的数据
【发布时间】:2018-05-08 19:02:55
【问题描述】:

我有一个调查问题,受访者可以在其中选择多个答案(针对 16 种可能的组合,例如“您喜欢哪种颜色?”可能会导致回答“红色、蓝色、绿色、黄色”或“红色、蓝色、绿色、黑色”等。

这 16 种可能的组合包含在电子表格中:

Image 1: First two rows of the spreadsheet (full spreadsheet has 16 rows)

示例 1:

structure(list(V1 = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L), .Label = c("red", "ruby"), class = "factor"), 
V2 = structure(c(1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 1L, 1L,
1L, 1L, 2L, 2L, 2L, 2L), .Label = c("blue", "violet"), class = "factor"), 
V3 = structure(c(1L, 1L, 2L, 2L, 1L, 1L, 2L, 2L, 1L, 1L, 
2L, 2L, 1L, 1L, 2L, 2L), .Label = c("green", "turqoise"), class = "factor"), 
V4 = structure(c(2L, 1L, 2L, 1L, 2L, 1L, 2L, 1L, 2L, 1L, 
2L, 1L, 2L, 1L, 2L, 1L), .Label = c("black", "yellow"), class = "factor")), .Names = c("V1", 
"V2", "V3", "V4"), class = "data.frame", row.names = c(NA, -16L
))

带有响应的数据框有十六列用于此问题(每种简单的颜色组合一列)。如果受访者 1 选择了第一个组合,则只有第一列包含数据;同样,如果受访者 2 选择了第二个组合,则第二列包含数据。其他都是空的:

Image 2: The first two columns of the dataframe

示例 2:

structure(list(respondentID = 1:16, v1 = c(1L, NA, NA, NA, NA,
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), v2 = c(NA, 1L, NA, 
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), v3 = c(NA, 
NA, NA, NA, NA, NA, 1L, NA, NA, NA, NA, NA, NA, NA, NA, NA), 
v4 = c(NA, NA, NA, 1L, NA, NA, NA, NA, NA, NA, 1L, 1L, NA, 
NA, NA, NA), v5 = c(NA, NA, 1L, NA, NA, NA, NA, NA, NA, NA, 
NA, NA, NA, NA, NA, NA), v6 = c(NA, 1L, NA, NA, NA, NA, NA, 
NA, NA, 1L, NA, NA, NA, NA, NA, NA), v7 = c(NA, NA, NA, NA, 
1L, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), v8 = c(NA, 
NA, NA, NA, NA, 1L, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA
), v9 = c(NA, NA, NA, NA, NA, NA, NA, 1L, NA, NA, NA, NA, 
NA, NA, NA, NA), v10 = c(NA, NA, NA, NA, NA, NA, NA, NA, 
NA, NA, NA, NA, NA, NA, NA, NA), v11 = c(NA, NA, NA, NA, 
NA, NA, NA, NA, 1L, NA, NA, NA, NA, NA, NA, NA), v12 = c(NA, 
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 1L, NA, NA, NA
), v13 = c(NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 
NA, 1L, NA, NA), v14 = c(NA, NA, NA, NA, NA, NA, NA, NA, 
NA, NA, NA, NA, NA, NA, NA, NA), v15 = c(NA, NA, NA, NA, 
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), v16 = c(NA, 
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 1L
)), .Names = c("respondentID", "v1", "v2", "v3", "v4", "v5", 
"v6", "v7", "v8", "v9", "v10", "v11", "v12", "v13", "v14", "v15", 
"v16"), class = "data.frame", row.names = c(NA, -16L))

(当然,在实践中被访者1不一定会选择组合1)。

数据框中的所有信息都是数字“1”,对应电子表格中的适当组合。

为了分析对问题的回答,我需要从电子表格中提取组合并将其与回答一起导入数据框中,以便我在数据框中获得四个新列,其中包含受访者选择的颜色组合 (例如,受访者 1) 的红色、蓝色、绿色、黄色。

我认为使用 apply 没有任何方法可以做到这一点,所以我想我需要编写一个 for 循环来提取和导入数据。有关如何执行此操作的任何建议?

【问题讨论】:

  • 寻求帮助时,您应该包含一个简单的reproducible example,其中包含可用于测试和验证可能解决方案的示例输入和所需输出。数据图片不是很有帮助。
  • 您发布的第二个数据框有 9 列加上 ID,而不是 16

标签: r loops for-loop dataframe


【解决方案1】:

如果您将第二个数据框设为长形,您可以只过滤每个人选择的组合,然后将第二个数据框与第一个数据框连接起来。这两个数据框具有组合标签,可以在两者之间进行协调以加入。

请注意,我将第一个数据框中的列名 df1_with_id 更改为 color1 等,因为否则您将在一个数据框中拥有 v1v2、...和V1, V2, ... 代表另一个不同的东西。不是必要的更改,但最好不要混淆不同变量的含义。

library(tidyverse)

df1 <- structure(list(V1 = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L,2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L), .Label = c("red", "ruby"), class = "factor"),V2 = structure(c(1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 1L, 1L,1L, 1L, 2L, 2L, 2L, 2L), .Label = c("blue", "violet"), class = "factor"),V3 = structure(c(1L, 1L, 2L, 2L, 1L, 1L, 2L, 2L, 1L, 1L,2L, 2L, 1L, 1L, 2L, 2L), .Label = c("green", "turqoise"), class = "factor"),V4 = structure(c(2L, 1L, 2L, 1L, 2L, 1L, 2L, 1L, 2L, 1L,2L, 1L, 2L, 1L, 2L, 1L), .Label = c("black", "yellow"), class = "factor")), .Names = c("V1","V2", "V3", "V4"), class = "data.frame", row.names = c(NA, -16L))

df2 <- structure(list(respondentID = 1:16, v1 = c(1L, NA, NA, NA, NA,NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), v2 = c(NA, 1L, NA,NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), v3 = c(NA,NA, NA, NA, NA, NA, 1L, NA, NA, NA, NA, NA, NA, NA, NA, NA),v4 = c(NA, NA, NA, 1L, NA, NA, NA, NA, NA, NA, 1L, 1L, NA,NA, NA, NA), v5 = c(NA, NA, 1L, NA, NA, NA, NA, NA, NA, NA,NA, NA, NA, NA, NA, NA), v6 = c(NA, 1L, NA, NA, NA, NA, NA,NA, NA, 1L, NA, NA, NA, NA, NA, NA), v7 = c(NA, NA, NA, NA,1L, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), v8 = c(NA,NA, NA, NA, NA, 1L, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), v9 = c(NA, NA, NA, NA, NA, NA, NA, 1L, NA, NA, NA, NA,NA, NA, NA, NA), v10 = c(NA, NA, NA, NA, NA, NA, NA, NA,NA, NA, NA, NA, NA, NA, NA, NA), v11 = c(NA, NA, NA, NA,NA, NA, NA, NA, 1L, NA, NA, NA, NA, NA, NA, NA), v12 = c(NA,NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 1L, NA, NA, NA), v13 = c(NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,NA, 1L, NA, NA), v14 = c(NA, NA, NA, NA, NA, NA, NA, NA,NA, NA, NA, NA, NA, NA, NA, NA), v15 = c(NA, NA, NA, NA,NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), v16 = c(NA,NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 1L)), .Names = c("respondentID", "v1", "v2", "v3", "v4", "v5","v6", "v7", "v8", "v9", "v10", "v11", "v12", "v13", "v14", "v15","v16"), class = "data.frame", row.names = c(NA, -16L))

df1_with_id <- df1 %>% 
    setNames(paste0("color", 1:4)) %>%
    mutate(combo = paste0("v", row_number()))

head(df1_with_id)
#>   color1 color2   color3 color4 combo
#> 1    red   blue    green yellow    v1
#> 2    red   blue    green  black    v2
#> 3    red   blue turqoise yellow    v3
#> 4    red   blue turqoise  black    v4
#> 5    red violet    green yellow    v5
#> 6    red violet    green  black    v6

df2 %>%
    gather(key = combo, value = val, -respondentID) %>%
    filter(!is.na(val)) %>%
    left_join(df1_with_id, by = "combo")
#>    respondentID combo val color1 color2   color3 color4
#> 1             1    v1   1    red   blue    green yellow
#> 2             2    v2   1    red   blue    green  black
#> 3             7    v3   1    red   blue turqoise yellow
#> 4             4    v4   1    red   blue turqoise  black
#> 5            11    v4   1    red   blue turqoise  black
#> 6            12    v4   1    red   blue turqoise  black
#> 7             3    v5   1    red violet    green yellow
#> 8             2    v6   1    red violet    green  black
#> 9            10    v6   1    red violet    green  black
#> 10            5    v7   1    red violet turqoise yellow
#> 11            6    v8   1    red violet turqoise  black
#> 12            8    v9   1   ruby   blue    green yellow
#> 13            9   v11   1   ruby   blue turqoise yellow
#> 14           13   v12   1   ruby   blue turqoise  black
#> 15           14   v13   1   ruby violet    green yellow
#> 16           16   v16   1   ruby violet turqoise  black

reprex package (v0.2.0) 于 2018 年 5 月 8 日创建。

【讨论】:

  • 代码正常工作,并将示例 2 数据帧中的响应正确连接到示例 1 数据帧中的组合。但是,代码只是复制适当的组合,例如, "red,blue,green,yellow" 形成一列,而不是分成四个特定颜色的列。我也无法使用更正的数据框(我在上面的已编辑问题中发布)重新创建您的代码。具体来说,我试图避免重用 ifelse,但找不到在不重新创建“combo”变量的情况下重写代码的方法。
  • 我发帖时没有看到更新的数据。您不必将颜色一起粘贴到一列中 - 这样对我来说似乎更易于管理,但不是必需的。 ifelse 位是因为没有统一的标签,否则不再需要,因为您有更清晰的标签。我马上更新
  • 这很好用。谢谢你,@卡米尔。对于将来可能遇到此问题的任何人,我唯一可以添加的就是将“arrange(respondentID)”添加到代码中。对于大多数用途,我想保留原始数据集(在此问题示例 2 数据框中)中的行号(如,对应于受访者)会更方便。
【解决方案2】:

我不确定你想做什么。使用 tidyverse 包和 reshape2 包的 melt() 函数,你可以试试

df_respondent_combination <-
  df_respondent %>%
  melt(measure.vars = c(2:ncol(.)), na.rm = T) %>%
  cbind(df_combination) %>%
  select(-variable, -value) %>%
  arrange(respondentID)

df_respondent_combination 是预期的新数据帧,df_respondent 是您的示例 2,df_combination 是您的示例 1。

【讨论】:

  • 谢谢。这可能是前进的方向,但是因为这两个数据帧的行数不同,所以我收到了错误消息。数据帧中的行数对于我想要做的事情并不重要,因为重点是检测 df_respondent 中的哪一列指示响应,然后使用该列的数量从具有相同数量的行中提取响应组合来自 df_combination。
  • 正如@camille 指出的那样,示例 2 只有 9 列。 (我已经修改了代码。)Jrmie,即使有正确的 16 列,您的代码也无法正常工作。我可以执行代码,并以正确的格式获取数据框,但变量与受访者实际做出的选择不对应。例如,根据df_respondent_combination,被调查者10选择了“红、蓝、绿、黄”,而在实际例子中被调查者10选择了“红、紫、绿、黑”。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-02-12
  • 2021-07-05
  • 2019-07-29
  • 2021-12-22
  • 2020-09-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多