我正在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
1994
,1995
等方式对数据进行分组。这样我就可以进行一些分析了。我尝试使用data set
和factor/level
按sapply
对subset
进行子集化。但是,我意识到R
只是将1994
和1995
视为一行中的数据。我想通过将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
答案 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
拆分df1
将addYear
应用于拆分的每个组件。最后把它们放回原处。没有包使用。
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