【问题标题】:Mapping row according to column value根据列值映射行
【发布时间】:2017-03-06 12:27:31
【问题描述】:

如果日志文件在 csv 中,则可以使用 merge 在 R/Python 中轻松完成此任务。

但是日志文件是用以下语法编写的

Key=1|Time=146656456446
Key=2|Time=146656456447
Key=1|Time=146656456448|field=10
Key=2|Time=146656456450|field=11

有什么方法可以合并它并通过以下方式获取差异

Key,Time1,Time2,diff,field
Key=1,146656456446,146656456448,2,10
Key=2,146656456447,146656456450,3,11

【问题讨论】:

  • 你能更准确一点吗?你知道可能的 Key 值的数量吗?如果任务在 R 或 Python 中很简单,是什么阻止您使用它们?
  • 键值用于映射到对应的时间戳(总会有一对,键值是整数)。如果格式使用列标题(如在 csv 中),任务很容易,我可以使用键列合并。希望我清楚
  • @pythonRcpp,读取数据,gsub 取出“Key=”和“Time=”,将数据重新整形为“宽”格式,并为差异添加一列。
  • 另外,你的“差异”似乎是错误的。
  • @A5C1D2H2I1M1N2O1R2T1 已更正:)

标签: python r merge


【解决方案1】:

将我的评论转换为答案,这是一种使用“data.table”包的方法。

library(data.table)
x <- "path/to/yourLogFile.txt"      
mydt <- fread(x, header = FALSE, col.names = c("Key", "Time"))

dcast(mydt[, Time := as.numeric(sub("Time=", "", Time))][
  , Ind := sequence(.N), Key], Key ~ Ind, value.var = "Time")[
    , Diff := `2` - `1`][]
#      Key            1            2 Diff
# 1: Key=1 146656456446 146656456448    2
# 2: Key=2 146656456447 146656456450    3

使用我的“splitstackshape”包的另一种类似方法以及读取数据的相同步骤可能如下所示:

library(splitstackshape)
dcast(getanID(cSplit(mydt, "Time", "="), "Key"), 
      Key ~ Time_1 + .id, value.var = "Time_2")[
        , Diff := Time_2 - Time_1, by = Key][]
#      Key       Time_1       Time_2 Diff
# 1: Key=1 146656456446 146656456448    2
# 2: Key=2 146656456447 146656456450    3

为了读取日志文件,我做了以下假设:

  • 您知道应该有两列。
  • 您的日志文件目前没有列名(因此是header = FALSE)。
  • 您希望数据由| 字符分隔,fread 将能够自动检测到。

更新

它并不漂亮,但它确实有效....

dcast(getanID(cSplit(mydt, names(mydt), "="), "Key_2"), 
      Key_2 ~ .id, fun=list(I, I), value.var = list("Field_2", "Time_2"), fill = 0)[
        , c("Field_2_I_1", "Diff") := list(NULL, Time_2_I_2 - Time_2_I_1)][]
##    Key_2 Field_2_I_2   Time_2_I_1   Time_2_I_2 Diff
## 1:     1          10 146656456446 146656456448    2
## 2:     2          11 146656456447 146656456450    3

样本数据

## Just to simulate a log file like the one you describe....
## "temp" would be your actual file....
x <- c("Key=1|Time=146656456446", "Key=2|Time=146656456447", 
       "Key=1|Time=146656456448|field=10", "Key=2|Time=146656456450|field=11")
temp <- tempfile() 
writeLines(x, temp)

mydt <- fread(temp, header = FALSE, fill = TRUE, 
              col.names = c("Key", "Time", "Field"))
mydt
##      Key              Time    Field
## 1: Key=1 Time=146656456446         
## 2: Key=2 Time=146656456447         
## 3: Key=1 Time=146656456448 field=10
## 4: Key=2 Time=146656456450 field=11

【讨论】:

  • 好久不见。很高兴你回来了!
  • @akrun,谢谢。不知道我有多“回来” :-) 这些天工作太多了!
  • 这主要适用于我,只是在每对中 1 行有 1 列额外。有没有办法将它包含到合并的行中?例如。 row1 Key=1|Time=123 row2 Key=1|Time=125|extraColumnVal=99 mergedRow2: 1,123,125,2,99
  • 已更新我的问题,好像我忘了在问题中添加 1 个额外的列值
  • @pythonRcpp,您为什么不再分享几行示例数据,这样您正在处理的内容和想要获得的输出就不会模棱两可了。例如,额外的列是否仅针对键的第二个实例出现?
【解决方案2】:

如果您不需要列中的时间,以下将起作用

library(tidyverse)
library(data.table)

df <- read_table(
"test       
Key=1|Time=146656456446  
Key=2|Time=146656456447  
Key=1|Time=146656456448  
Key=2|Time=146656456450" )

用“|”分隔字符串然后通过“=”获取号码

df <-
df %>% 
  separate(test, into = c("Key", "Time"), sep = "\\|") %>% 
  separate(Time, into = c("Timepoint", "Time"), sep = "=")

df
# A tibble: 4 × 3
    Key Timepoint         Time
* <chr>     <chr>        <chr>
1 Key=1      Time 146656456446
2 Key=2      Time 146656456447
3 Key=1      Time 146656456448
4 Key=2      Time 146656456450

将时间更改为数字并按键分组以计算差异

df$Time <- as.numeric(df$Time)

df <-
df %>% 
  group_by(Key) %>% 
  summarise(Diff = diff(Time))

df
# A tibble: 2 × 2
    Key  Diff
  <chr> <dbl>
1 Key=1     2
2 Key=2     3

【讨论】:

    猜你喜欢
    • 2019-07-18
    • 1970-01-01
    • 1970-01-01
    • 2022-11-24
    • 1970-01-01
    • 2022-11-16
    • 2021-09-29
    • 1970-01-01
    • 2020-07-12
    相关资源
    最近更新 更多