在R中组织多维数据

时间:2016-07-26 05:51:41

标签: r

我正在multidimensional data组织R。数据从R CSV文件中提取。我在R数据框中的数据如下:

 Rank     Arrangers     YearAmt
                         1994
 1         JPM          6,605.00
 2         UBS          7,806.00
 3         RBS          1,167.34

                         1995  
 1         Citi         1,150.00
 2         Scotiabank   483.33
 3         ING          800.56
 4         UniCredit    700.70

这只是一个玩具数据。原始数据集很大。我希望按year 19941995等方式对数据进行分组。这样我就可以进行一些分析了。我尝试使用data setfactor/levelsapplysubset进行子集化。但是,我意识到R只是将19941995视为一行中的数据。我想通过将csv创建为单独的Year,然后在column中为所有year添加相应的field来格式化原始rows文件1}}。

对于在R中建议组织数据的方法,我们将不胜感激。我期待这样的输出:

Rank       Arrangers    YearAmt    Year 
 1         JPM          6,605.00   1994
 2         UBS          7,806.00   1994
 3         RBS          1,167.34   1994
 1         Citi         1,150.00   1995
 2         Scotiabank   483.33     1995
 3         ING          800.56     1995
 4         UniCredit    700.70     1995

3 个答案:

答案 0 :(得分:2)

1)ave 使用cumsum(Rank == "")创建分组变量多年,这会使用ave创建在每年的年度行组中创建的Year列a Year由NA组成,后面是重复的年份。最后使用na.omit删除带NA的行。没有使用包裹:

na.year <- function(x) c(NA, rep(x[1], length(x) - 1))  # c(NA, x[1], x[1], ..., x[1])
na.omit( transform(df1, Year = ave(YearAmt, cumsum(Rank == ""), FUN = na.year)) ) 

使用@akrun答案中可重复定义的输入df1,我们得到:

  Rank  Arrangers  YearAmt Year
2    1        JPM 6,605.00 1994
3    2        UBS 7,806.00 1994
4    3        RBS 1,167.34 1994
6    1       Citi 1,150.00 1995
7    2 Scotiabank   483.33 1995
8    3        ING   800.56 1995
9    4  UniCredit   700.70 1995

2)使用by拆分df1addYear应用于拆分的每个组件。最后把它们放回原处。没有包使用。

addYear <- function(x) cbind(x[-1, ], Year = x[1, "YearAmt"])
do.call("rbind", by(df1, cumsum(df1$Rank == ""), addYear))

3)sqldf 使用sqldf包,我们可以加入df1的每一行,其中所有先前的行具有零长度等级Rank,取最大值{{1}形成YearAmt的那些。然后只保留长度为{0}的非零行。

Year

答案 1 :(得分:1)

我们根据&#39; Rank&#39;中的空白元素创建逻辑向量。 (&#39; i1&#39;),然后对&#39; df1&#39;的行进行子集化。通过使用&#39; i1&#39;删除所有空白行(df1[!i1,])和transform数据集用于创建“年份”数据集。通过复制&#39; YearAmt&#39; (对应于&#39; Rank&#39;中的空白),使用&#39; i1&#39;的累积总和。

i1 <- df1$Rank == ''
res <- transform(df1[!i1,], Year = df1$YearAmt[i1][cumsum(i1)[!i1]])
res
#  Rank  Arrangers  YearAmt Year 
#2    1        JPM 6,605.00 1994
#3    2        UBS 7,806.00 1994
#4    3        RBS 1,167.34 1994
#6    1       Citi 1,150.00 1995
#7    2 Scotiabank   483.33 1995
#8    3        ING   800.56 1995
#9    4  UniCredit   700.70 1995

或者正如@ G.Grothendieck在评论中提到的那样,transform步骤可以通过

来实现。
res <- transform(df1, Year = YearAmt[i1][cumsum(i1)])[!i1, ]
row.names(res) <- NULL

注意:不需要外部包。只有baseverse ..

或使用dtverse/zooverse

library(data.table)
library(zoo)
setDT(df1)[Rank=='', Year:= YearAmt][, Year := na.locf(Year)][Rank!='']
#   Rank  Arrangers  YearAmt Year
#1:    1        JPM 6,605.00 1994
#2:    2        UBS 7,806.00 1994
#3:    3        RBS 1,167.34 1994
#4:    1       Citi 1,150.00 1995
#5:    2 Scotiabank   483.33 1995 
#6:    3        ING   800.56 1995
#7:    4  UniCredit   700.70 1995

数据

df1 <- structure(list(Rank = c("", "1", "2", "3", "", "1", "2", "3", 
"4"), Arrangers = c("", "JPM", "UBS", "RBS", "", "Citi", "Scotiabank",   
"ING", "UniCredit"), YearAmt = c("1994", "6,605.00", "7,806.00", 
"1,167.34", "1995", "1,150.00", "483.33", "800.56", "700.70")), 
.Names = c("Rank", 
"Arrangers", "YearAmt"), row.names = c(NA, -9L), class = "data.frame")

答案 2 :(得分:1)

tidyverse选项:

library(dplyr)
library(tidyr)

       # add Year column, with NAs where no year in row
df %>% mutate(Year = ifelse(Rank == '' & Arrangers == '', YearAmt, NA)) %>% 
  # fill year downwards
  fill(Year) %>% 
  # chop out year rows
  filter(Rank != '', Arrangers != '')

##   Rank  Arrangers  YearAmt Year
## 1    1        JPM 6,605.00 1994
## 2    2        UBS 7,806.00 1994
## 3    3        RBS 1,167.34 1994
## 4    1       Citi 1,150.00 1995
## 5    2 Scotiabank   483.33 1995
## 6    3        ING   800.56 1995
## 7    4  UniCredit   700.70 1995