【问题标题】:How to divide unequal dataframes in R with missing data如何在 R 中将不相等的数据框与缺失数据分开
【发布时间】:2016-01-01 16:08:36
【问题描述】:

我有两个不同维度的数据框。并想划分两个数据框。我的原始数据框没有。超过 4000 的列,因此,给出每列的名称可能很麻烦。此外,如下图所示,一个数据框中的列可能在其他数据框中没有相应的列。而列名A.SA是公司名称,S表示公司A的价格数据,A.V表示公司A的成交量数据。我的样本量是从 2000 年到 2014 年的一个重要细节。所以,如果 A 公司在 2002 年开始交易,它将在 2000 年和 2001 年有 NA。那么,我应该如何解决这个问题。

df1<- S
         Date      A.S B.S  C.S
        01/01/2000  1   10  19
        02/01/2000  2   11  20
        03/01/2000  3   12  21
        04/01/2000  NA  13  22
        05/01/2000  NA  14  23
        06/01/2000  NA  NA  24
        07/01/2000  7   NA  25
        08/01/2000  8   NA  26
        09/01/2000  9   18  27
 The other dataframe 
df2<-V
    Date        A.V B.V
    01/01/2000  12  NA
    02/01/2000  12  NA
    03/01/2000  12  3
    04/01/2000  12  4
    05/01/2000  12  5
    06/01/2000  NA  6
    07/01/2000  NA  7
    08/01/2000  NA  8
    09/01/2000  NA  9

并希望得到如下的结果。 T

    df3<-df1/df2
 Date        A      B   C
01/01/2000  0.08    NA  NA
02/01/2000  0.17    NA  NA
03/01/2000  0.25    4   NA
04/01/2000  NA      3   NA
05/01/2000  NA      3   NA
06/01/2000  NA      NA  NA
07/01/2000  NA      NA  NA
08/01/2000  NA      NA  NA
09/01/2000  NA      2   NA

非常感谢您的帮助

【问题讨论】:

  • 您已经尝试过什么了吗?为什么它不起作用?每个数据帧的日期列是否相同?
  • 我认为您需要 (i) 转换为矩阵,(ii) 匹配日期,(iii) 将具有相同日期的列分开,并为已经有 NA 的任何值返回 NA .假设我已经了解您想要做什么。
  • @Heroka 我试过 'df3
  • @user1945827 实际上我的两个数据框的编号相同。行数,即日期。我想忽略日期列上的除法运算并在休息时运行它。但列不一样。
  • @Heroka 是日期列对于两个数据帧是相同的,我没有。行数,即日期

标签: r dataframe division missing-data


【解决方案1】:

有几种方法可以解决这个问题。一种方法是使用正则表达式使列名同质化(我为此创建了“编辑”数据框,您当然可以使用原始数据进行此操作。

#edit column names
df1_edit <- df1
colnames(df1_edit) <- gsub("\\.S","",colnames(df1_edit))

df2_edit <- df2
colnames(df2_edit) <- gsub("\\.V","",colnames(df2_edit))

#create vector of all columns that need to be made, excluding 'Date'
all_cols <- unique(c(colnames(df1_edit)[-1],colnames(df2_edit)[-1]))

#create missing columns
df1_edit[,setdiff(all_cols,colnames(df1_edit))] <- NA
df2_edit[,setdiff(all_cols,colnames(df2_edit))] <- NA

#now divide the dataframes, using all_cols to ensure correct order (and thus division)
res <- cbind(Date=df1_edit$Date, df1_edit[,all_cols]/df2_edit[,all_cols])
> res
        Date          A         B  C
1 01/01/2000 0.08333333 10.000000 NA
2 02/01/2000 0.16666667  5.500000 NA
3 03/01/2000 0.25000000  4.000000 NA
4 04/01/2000 0.33333333  3.250000 NA
5 05/01/2000 0.41666667  2.800000 NA
6 06/01/2000 0.50000000  2.500000 NA
7 07/01/2000 0.58333333  2.285714 NA
8 08/01/2000 0.66666667  2.125000 NA
9 09/01/2000 0.75000000  2.000000 NA

另一种方法是进行一些数据重塑。首先,我们将两个数据帧都转换为 long 并操作“变量”变量。然后我们合并(all=T 生成我们的 NA),划分并重塑为宽。

library(data.table)

df1_l <- melt(setDT(df1),id.var="Date", value.var="value.S")
df1_l$var <-gsub("\\.S","",df1_l$variable)
df2_l <- melt(setDT(df2), id.var="Date",value.var="value.V")
df2_l$var <-gsub("\\.V","",df2_l$variable)

df_merge <- merge(df1_l, df2_l, by=c("Date","var"),all=T)
df_merge$res <- df_merge$value.x/df_merge$value.y

res <- dcast(df_merge, Date~var,value.var="res")

> res
         Date          A         B  C
1: 01/01/2000 0.08333333 10.000000 NA
2: 02/01/2000 0.16666667  5.500000 NA
3: 03/01/2000 0.25000000  4.000000 NA
4: 04/01/2000 0.33333333  3.250000 NA
5: 05/01/2000 0.41666667  2.800000 NA
6: 06/01/2000 0.50000000  2.500000 NA
7: 07/01/2000 0.58333333  2.285714 NA
8: 08/01/2000 0.66666667  2.125000 NA
9: 09/01/2000 0.75000000  2.000000 NA

【讨论】:

  • 感谢您的回答,但我在解释我的情况时犯了错误,并再次更新了帖子。 “我的样本量是从 2000 年到 2014 年的一个重要细节。所以,如果 A 公司在 2002 年开始交易,它将在 2000 年和 2001 年有 NA。那么,我应该如何解决这个问题。请您看一下,因为当我运行此代码时,我收到了一个数据框,其中添加了超过 9000 列
  • 我认为这与日期无关,而是与列名的模式有关。它们与您示例中的名称不同吗?然后需要更改正则表达式。
  • 是的,列的名称与示例不同,例如公司名称(列标题)数据框是 A.G.L.SJ.INVS...LON..DEAD...13.08.15。 ..TURNOVER.BY.VOLUME 在其他数据框中,它的名称是 A.G.L.SJ.INVS...LON..DEAD...13.08.15...S。我的数据集中有 4998 家公司。那么,应该如何更改正则表达式。并且 'colnames (df1_edit)
  • 您需要使(几乎)任何解决方案的列标题统一,@Parfait 的答案向您展示了如何做到这一点。
【解决方案2】:

考虑使用交叉列和不同列比较的mapply 路线:

# OBTAIN SAME/DIFFERENT COLUMNS USING REGEX FOR SUFFIX
samecols <- intersect(unlist(gsub("\\.*S$", "", names(df1)[2:ncol(df1)])), 
                      unlist(gsub("\\.*TURNOVER.BY.VOLUME$", "", names(df2)[2:ncol(df1)])))

diffcols <- setdiff(unlist(gsub("\\.*S$", "", names(df1))), 
                    unlist(gsub("\\.*TURNOVER.BY.VOLUME$", "", names(df2))))

# DEFINED DIV FUNCTION
divfct <- function(var1, var2){
            return (var1/var2)
          }

# MAPPLY USING DIV FUNCTION
fctresults <- as.data.frame(mapply(divfct, var1=df1[, paste0(samecols, ".S")],
                                   var2=df2[, paste0(samecols, "...TURNOVER.BY.VOLUME")]))

# MONTHLY DATES: 2000-2014
datelist <- lapply(1:12, function(m) {
                         lapply(2000:2014, function(y) paste(m, "1", y, sep="/"))
        })
datedf <- data.frame(Date=unlist(datelist))

# MERGE DATE AND DIV FUNCTION RESULTS
finaldf <- cbind(list(Date = df1[,c("Date")]), fctresults)
finaldf <- merge(datedf, finaldf, by="Date", all=TRUE)
finaldf$Date <- strptime(finaldf$Date, "%m/%d/%Y")     # CONVERT COLUMN TO DATE (POSIXlt)
finaldf <- finaldf[order(finaldf$Date),]               # RE-ORDER BY DATE (POSIXlt)
row.names(finaldf) <- 1:nrow(finaldf)                  # RESET ROW NAMES

for (i in diffcols) {
  finaldf[[i]] <- NA
}

# REMOVE TEMP OBJECTS
rm(i, diffcols, samecols, fctresults, divfct, datedf, datelist)

【讨论】:

  • 谢谢你的回答其实我错过了一个细节。并更新了我的帖子,请你看一下。
  • 我在我的问题中为更新的数据框运行了这段代码,它运行良好,并提供了所需的数据框输出。但是公司名称公司名称(列标题)数据框是 A.G.L.SJ.INVS...LON..DEAD...13.08.15...TURNOVER.BY.VOLUME 而在其他数据框中它的名称是A.G.L.SJ.INVS...LON..DEAD...13.08.15...S.我的数据集中有 4998 家公司。我尝试了几件事来更改此代码,但没有运气。您能否指导我如何更改以我提供的名称示例查找相同的列。非常感谢您的帮助。
  • 只有一个公司名称,包括ellipsis(...),只是数据帧之间的结尾不同吗?
  • 对于名称以 S 结尾的公司的数据框。在 S. (...) 之前有不同的省略号,但都以 S 结尾。而在公司名称以 TURNOVER.BY.VOLUME 结尾的数据框中有相同的号码。省略号,即三个没有。在营业额之前。我希望这就是您要问的。
  • 查看更新以处理实际列名,甚至解析每月日期,2000-2014。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-26
  • 1970-01-01
  • 2016-11-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多