【问题标题】:R subset ordered factorR子集有序因子
【发布时间】:2014-01-09 01:40:23
【问题描述】:

我有以下 data.frame,它报告了各国在不同年份的各种数据。数据按城市/农村、城市贫民窟/城市非贫民区和首都/其他城市中心分类。遗憾的是,数据有点不完整,因此并非每个国家/地区都在同一年报告了所有指标的数据。

我正在尝试对数据进行子集化以生成一些图表来比较每个国家/地区的最新数据。我在 data.frame 中创建了一个名为“latest”的列,它报告一行是否是最近一年。但是,当我试图比较贫民窟/非贫民窟时 - 可用的数据并不总是最新的。因此,我想创建一个子集,以查看给定行中是否存在数据,如果不是,我想选择最近一年的数据。

我觉得这可以通过使用因子变量“年份”的顺序来实现,但不知道如何去做。我只能选择其中包含数据的行,但这会为每个国家/地区提供多个条目,如下所示:

fever[(fever$Non.slum!='NA'),]

产生这个:

      COUNTRY   Year    Urban    Rural    Total Capital.City Other.Cities..towns Non.slum Slum latest
NA       <NA>   <NA>       NA       NA       NA           NA                  NA       NA   NA   <NA>
NA.1     <NA>   <NA>       NA       NA       NA           NA                  NA       NA   NA   <NA>
3    Ethiopia   2011 14.78709 16.03735 15.87641     11.86713            15.28213     10.6 15.4      y
4    Ethiopia   2005 16.00000 18.90000 16.90000     15.70000            16.10000     15.0 16.1      n
5    Ethiopia   2000 22.38637 25.18128 24.90000     19.49970            22.86689     19.9 22.6      n
6       Kenya 2008/9 20.71574 22.58868 22.20000     16.99561            22.39136     19.2 21.8      y
7       Kenya   2003 39.78713 40.75334 40.56866     38.45388            40.49664     31.7 42.8      n
8       Kenya   1998 41.67932 42.44481 42.30155     38.79310            43.27112     36.3 43.7      n
NA.2     <NA>   <NA>       NA       NA       NA           NA                  NA       NA   NA   <NA>
10    Lesotho   2009 12.93654 16.22281 17.90000     13.25208            12.69136     11.7 13.6      y

所以我需要一个函数来仅选择数据存在于 Slum/Non.Slum 列中的那些行,但根据可用的最新数据,每个 COUNTRY 仅选择一个条目。

我已经在论坛中搜索过,试图找到答案,但没有走得太远:(

谁能提供任何方便的建议?

谢谢

附言这是我的数据:

structure(list(COUNTRY = structure(c(1L, 2L, 3L, 3L, 3L, 4L, 
4L, 4L, 4L, 5L, 5L, 6L, 6L, 6L, 6L, 7L, 7L, 7L, 7L, 7L, 7L, 8L, 
8L, 8L, 9L, 9L, 9L, 9L, 9L, 10L, 11L, 11L, 11L, 11L, 11L, 11L, 
12L, 12L, 12L, 13L, 13L, 13L, 13L, 14L, 14L, 14L, 14L), .Label = c("Comoros", 
"Eritrea", "Ethiopia", "Kenya", "Lesotho", "Madagascar", "Malawi", 
"Namibia", "Rwanda", "Swaziland", "Tanzania", "Uganda", "Zambia", 
"Zimbabwe"), class = "factor"), Year = structure(c(5L, 12L, 25L, 
16L, 9L, 22L, 13L, 7L, 2L, 23L, 15L, 22L, 14L, 6L, 1L, 24L, 15L, 
9L, 1L, 13L, 6L, 19L, 9L, 1L, 24L, 21L, 16L, 9L, 1L, 19L, 24L, 
21L, 15L, 8L, 5L, 1L, 18L, 10L, 4L, 20L, 11L, 5L, 1L, 24L, 17L, 
8L, 3L), .Label = c("1992", "1993", "1994", "1995", "1996", "1997", 
"1998", "1999", "2000", "2000/1", "2001/2", "2002", "2003", "2003/4", 
"2004", "2005", "2005/6", "2006", "2006/7", "2007", "2007/8", 
"2008/9", "2009", "2010", "2011"), class = "factor"), Urban = c(47.8, 
24.2, 14.7870851371451, 16, 22.3863741902043, 20.7157413622361, 
39.7871349722997, 41.6793203690612, 35.8582154033059, 12.9365423294414, 
19.8478428266605, 11.9207464780274, 18.5676950229307, 27.6081260825543, 
22.9, 30.7, 29.8676525754328, 28.8769863995411, 36.7350808997634, 
23.6685395495197, 43.5924904552921, 15.3818829930695, 20.9, 28.4927963558185, 
16.7, 18.1130004296917, 25.3, 19, 32.2, 17.6, 29.7, 20.7, 22.5, 
29.6313219134818, 30.5, 31.6001273852453, 25, 32.9, 35.2, 16.3, 
33.1, 38.1, 33.7, 8.65178666948846, 7.3, 22.6, 34.5), Rural = c(47.6, 
32.7, 16.0373484732733, 18.9, 25.181276309133, 22.5886832681651, 
40.7533401938621, 42.4448145032958, 38.5298174751626, 16.2228067346473, 
26.465049129342, 8.41898094643249, 19.2257425400682, 29.635864119259, 
27.7, 35.1, 38.283749104983, 37.0204386868532, 40.4553536902836, 
23.6050855848523, 38.7593744908809, 16.2668541968914, 18.7, 36.7752452450324, 
15.6, 20.1615269604521, 26.4, 31, 42.1, 30.3, 21.2, 18.4, 24.9, 
31.338473181485, 30.3, 26.3897272106662, 43, 45.3, 47.8, 18.5, 
47.6, 41.4, 51.8, 10.1757289609584, 7.6, 27.3, 41.5), Total = c(47.6, 
29.8, 15.8764113925424, 16.9, 24.9, 22.2, 40.5686598193627, 42.3015496943942, 
38.2, 17.9, 25.5279161214695, 8.8, 19.1, 29.2, 27.1, 34.5, 37.1294935260729, 
36, 40.0371752616418, 23.6, 39.8, 15.9, 19.4, 34.0357824734553, 
15.8, 19.9, 26.2, 29.1, 41.6, 27.5, 22.9, 18.8, 24.4, 31, 30.3, 
27.5, 40.9, 43.9, 46.3, 17.8, 43.1, 40.1, 43.2, 9.72279457486365, 
7.5, 25.8, 39.7), Capital.City = c(62.5, 19.3, 11.8671319871973, 
15.7, 19.4996995263646, 16.99560676463, 38.4538776537224, 38.7931034482758, 
34.1584158415842, 13.2520773874409, 12.7659574468085, 15.6873992936943, 
14.9619843565563, 20.3036710627491, 19.5, NA, 32.011454861578, 
26.1111111111111, 33.2046332046333, 27.514648271213, 43.2946409100591, 
17.6134198692098, 21.2, 28.4927963558185, 17.4, 16.0904522908004, 
26.6, 22.7, 31.5, 13.4, NA, NA, 26.1, 29.1331564646512, 29.4, 
33.3949166628871, 18.9, 29.8, 30.5, 11, 32.3, 38.7, 26.3, 7.0408031903801, 
9.8, 26.7, 38.5), Other.Cities..towns = c(43.7, 27.7, 15.2821312519876, 
16.1, 22.8668864784677, 22.3913621285115, 40.4966412598569, 43.2711212401314, 
36.8054151596036, 12.6913635462951, 25.601742942828, 9.93629083208327, 
20.5991643631925, 31.5220710266449, NA, NA, 28.6811759983293, 
30.211847684812, 38.1705931383969, 22.8969512882811, 43.6420373588114, 
13.7990084372002, 20.4, 28.6992700604113, NA, 19.6243357194177, 
24.4, 17.5, 33, 22.1, NA, NA, 21.5, 29.7793073823722, 30.9, 31.1616047201402, 
29.9, 35.6, 39.4, 18.5, 33.4, 37.7, 36.3, 10.2081343223745, 5.3, 
18.9, 30), Non.slum = c(NA, NA, 10.6, 15, 19.9, 19.2, 31.7, 36.3, 
NA, 11.7, 18.8, NA, NA, NA, NA, NA, 24.7, 25.3, 33.7, 13.6, 35.1, 
15.6, 19.4, 36.8, NA, 15.4, 21.1, NA, 21.6, 18.1, NA, NA, 21.6, 
35.7, 24, 32, 15.9, 30.8, 28.4, 13.9, 28.5, 35.7, 29.3, 7.6, 
7.2, 21.8, 29.7), Slum = c(NA, NA, 15.4, 16.1, 22.6, 21.8, 42.8, 
43.7, NA, 13.6, 21.3, NA, NA, NA, NA, NA, 31.4, 31, 37, 24.2, 
44.8, 15.1, 23, 34, NA, 18.8, 27, NA, 34.9, 17.1, NA, NA, 22.8, 
26.5, 32.3, 31.5, 28.5, 34.2, 36, 17.9, 38.6, 39.3, 35.7, 10.1, 
7.4, 31.4, 41.1), latest = structure(c(2L, 2L, 2L, 1L, 1L, 2L, 
1L, 1L, 1L, 2L, 1L, 2L, 1L, 1L, 1L, 2L, 1L, 1L, 1L, 1L, 1L, 2L, 
1L, 1L, 2L, 1L, 1L, 1L, 1L, 2L, 2L, 1L, 1L, 1L, 1L, 1L, 2L, 1L, 
1L, 2L, 1L, 1L, 1L, 2L, 1L, 1L, 1L), .Label = c("n", "y"), class = "factor")), .Names = c("COUNTRY", 
"Year", "Urban", "Rural", "Total", "Capital.City", "Other.Cities..towns", 
"Non.slum", "Slum", "latest"), row.names = c(NA, -47L), class = "data.frame")

【问题讨论】:

  • 可以使用年份来执行此操作,或者更好地在 'max(year)' 上灵活设置子集,但是因为您有像“2008/9”这样的条目,所以您无法在“年份”上执行数字运算
  • 您好,感谢您的评论。如下所示,我试图避开这条路线,但这可能是最简单的方法。我可以使用fever$Year &lt;- substr(fever$Year, 0, 4) 之类的方法轻松转换 Year 列中的值,然后再转换为fever$Year &lt;- as.numeric(as.character(fever$Year)) 之类的方法。但我不完全确定如何使用 max() 进行子集化?

标签: r r-factor


【解决方案1】:

您可以使用subset 仅选择No.slumSlum 都不是NA 的那些行。然后,这个子集tmp 可用于删除具有重复COUNTRYs 的行。因此,只会保留最新的 Year 的行。

tmp <- subset(fever, !is.na(Non.slum) & !is.na(Slum))
res <- tmp[!duplicated(tmp$COUNTRY), ]

这会返回:

     COUNTRY   Year     Urban    Rural     Total Capital.City Other.Cities..towns Non.slum Slum latest
3   Ethiopia   2011 14.787085 16.03735 15.876411    11.867132            15.28213     10.6 15.4      y
6      Kenya 2008/9 20.715741 22.58868 22.200000    16.995607            22.39136     19.2 21.8      y
10   Lesotho   2009 12.936542 16.22281 17.900000    13.252077            12.69136     11.7 13.6      y
17    Malawi   2004 29.867653 38.28375 37.129494    32.011455            28.68118     24.7 31.4      n
22   Namibia 2006/7 15.381883 16.26685 15.900000    17.613420            13.79901     15.6 15.1      y
26    Rwanda 2007/8 18.113000 20.16153 19.900000    16.090452            19.62434     15.4 18.8      n
30 Swaziland 2006/7 17.600000 30.30000 27.500000    13.400000            22.10000     18.1 17.1      y
33  Tanzania   2004 22.500000 24.90000 24.400000    26.100000            21.50000     21.6 22.8      n
37    Uganda   2006 25.000000 43.00000 40.900000    18.900000            29.90000     15.9 28.5      y
40    Zambia   2007 16.300000 18.50000 17.800000    11.000000            18.50000     13.9 17.9      y
44  Zimbabwe   2010  8.651787 10.17573  9.722795     7.040803            10.20813      7.6 10.1      y

【讨论】:

  • 完美,正是我需要的!传奇人物,谢谢。
  • 这种方法之所以有效,是因为您的 data.frame 按国家然后按年份排序,而duplicated() 选择第一种情况。否则它将无法正常工作。看看这个:df&lt;-df[order(df$COUNTRY, df$Year),];&gt; tmp &lt;- subset(df, !is.na(Non.slum) &amp; !is.na(Slum));&gt; res &lt;- tmp[!duplicated(tmp$COUNTRY), ]。使用此方法检查第一个出现的国家/地区始终是最近的年份时要小心
  • @ECII 我完全清楚这一点。我认为使用已知的数据结构是最简单的。
  • @SvenHohenstein。这并不意味着批评。请注意,以防 OP 想将此解决方案用于另一个问题或数据集。
  • @ECII 一切都很好。我完全同意你的说法。
【解决方案2】:

以下是您可以遵循的一些指示。既然您问我需要一个函数来仅选择数据存在于 Slum/Non.Slum 列中的那些行,但根据可用的最新数据,每个 COUNTRY 仅选择一个条目,我建议:

  1. 考虑 R 中的 complete.cases 函数以仅选择数据存在于 Slum/No.Slum 列中的那些行。为此,您需要首先将数据子集到这两列中(例如,放入一个新的数据框),然后应用complete.cases。结果是TRUE/FALSE 的向量,用于对完整数据集进行子集化。

  2. 由于您希望在上述第 1 步中的子集数据框中为每个国家/地区提供一个条目,并且该单个条目基于最近一年,因此您可以首先按 Year 列对数据框进行排序(将年份数字视为数字)在每个 COUNTRY 内,然后选择每个 COUNTRY 的第一个条目以确保您选择了最近的一年。一个问题是,在年份排序部分,某些条目(例如2008/9)可能会造成问题。小心这些条目。

【讨论】:

  • 嗨,感谢您的提示。我曾认为这是一种解决方案,但会涉及我将所有“年份”条目转换为数值,也许通过重新评估每个条目以仅读取前四个字符/数字。我试图避免这种情况,但我确信我可以弄清楚如何以某种方式重新评估......
【解决方案3】:

我怀疑你想要的东西比你问的具体问题更通用。这是我的尝试,它也适用于其他变量

通过粘贴国家和年份创建一个新的ID,我们称之为country.year

df$country.year<-paste(df$COUNTRY, df$Year, sep="-")

您说您不想在 Slum 和 Non.slum 中使用 NA,因此我们将它们删除到 REDUCED 数据集

df.red<-df[ !is.na(df$Slum) & !is.na(df$Non.slum) ,]

我们构建了一个查找表,输出每个国家/地区的最大年份(减少数据集的最大年份,因为您不希望 NA 在 Slum/Non.slum 中)

lookup<-tapply(as.numeric(df.red$Year), df.red$COUNTRY, max)

我们重新格式化查找表以成为最大的国家/地区年份

lookup<-paste(rownames(lookup), as.numeric(lookup), sep="-")

现在我们从 REDUCED 数据集中过滤所有不在查找中的国家/地区年份

df.reconstructed<-df.red[  lookup %in% df$country.year  , ]

希望对你有帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多