String 用R识别复杂字符串中的多个id

String 用R识别复杂字符串中的多个id,string,r,String,R,我有一个数据帧,有很多字符串和这样的值 ID String Value 1 LocationID=123,321,345&TimeID=456,321,789&TypeID=12,32 100 2 LocationID=123,345&TimeID=456,321 50 3 LocationID=123,321,

我有一个数据帧,有很多字符串和这样的值

ID String                                                    Value
1  LocationID=123,321,345&TimeID=456,321,789&TypeID=12,32    100
2  LocationID=123,345&TimeID=456,321                         50
3  LocationID=123,321,345&TypeID=32                          120
...
正如您在示例中看到的,“,”表示“或”。因此locationID=123321345指的是那些具有位置ID 123、321或345的元素。“值”可以被认为是满足字符串的条目数

我想编写一个程序,用R计算每个ID的出现次数。也就是说,程序的输出应该是:

ID                Occurrence
LocationID = 123  270                          #(100+50+120)
LocationID = 321  220                          #(100+120)
...
TypeID = 12       100
...
有谁能给我一些关于如何做这项工作的建议吗

我发现很难处理“,”和ID。否则我可以使用for循环,尽管我讨厌for循环

还有一个问题,ID应该允许空字符或字符,如下所示:

ID String                                                    Value
1  LocationID=123,321,345&TimeID=456,321,789&TypeID=         100
2  LocationID=123,345&TimeID=&TypeID=A                       50
3  LocationID=123,321,345&TypeID=32                          120
temp2
#    ID Measure      Param Value
# 1   1     123 LocationID   100
# 2   1     321 LocationID   100
# 3   1     345 LocationID   100
# 4   1     456     TimeID   100
# 5   1     321     TimeID   100
# 6   1     789     TimeID   100
# 7   1      12     TypeID   100
# 8   1      32     TypeID   100
# 9   2     123 LocationID    50
# 10  2     345 LocationID    50
# 11  2     456     TimeID    50
# 12  2     321     TimeID    50
# 13  3     123 LocationID   120
# 14  3     321 LocationID   120
# 15  3     345 LocationID   120
# 16  3      32     TypeID   120

尝试使用strsplit函数,您可以像这样标记字符串

strsplit("LocationID=123,321,345&TimeID=456,321,789&TypeID=12,32","&"); ## this will tokenize by splitting by &;
然后使用grep确定LocationID、TimeID、TypeID的存在,并通过“=”和“,”将值附加到辅助帧中来适当地设置strsplit

最后叫一个“tapply”


希望这有助于概括

尝试使用strsplit函数,您可以像这样标记字符串

strsplit("LocationID=123,321,345&TimeID=456,321,789&TypeID=12,32","&"); ## this will tokenize by splitting by &;
然后使用grep确定LocationID、TimeID、TypeID的存在,并通过“=”和“,”将值附加到辅助帧中来适当地设置strsplit

最后叫一个“tapply”


希望这有助于概括你可以这样做

dat <- read.table(text = 'ID String                                                    Value
1  LocationID=123,321,345&TimeID=456,321,789&TypeID=12,32    100
2  LocationID=123,345&TimeID=456,321                         50
3  LocationID=123,321,345&TypeID=32                          120',header= T, stringsAsFactors=F)
## split by &
ll <- unlist(strsplit(dat$String,'&'))
## create 2 lits of occuonces and id names
occs <- strsplit(gsub('(.*)ID=(.*)','\\2',ll),',')
ids <- gsub('(.*)ID=(.*)','\\1',ll)
names(occs) <- ids
ll <- sapply(names(occs),function(x) occs[x] <- paste(x,occs[[x]], sep ='_'))
## use rapply to change list in data.frame then count by table
table(rapply(ll,I))

Location_123 Location_321 Location_345     Time_321     Time_456     Time_789      Type_12      Type_32 
           3            3            3            2            2            2            2            2 

dat您可以这样做

dat <- read.table(text = 'ID String                                                    Value
1  LocationID=123,321,345&TimeID=456,321,789&TypeID=12,32    100
2  LocationID=123,345&TimeID=456,321                         50
3  LocationID=123,321,345&TypeID=32                          120',header= T, stringsAsFactors=F)
## split by &
ll <- unlist(strsplit(dat$String,'&'))
## create 2 lits of occuonces and id names
occs <- strsplit(gsub('(.*)ID=(.*)','\\2',ll),',')
ids <- gsub('(.*)ID=(.*)','\\1',ll)
names(occs) <- ids
ll <- sapply(names(occs),function(x) occs[x] <- paste(x,occs[[x]], sep ='_'))
## use rapply to change list in data.frame then count by table
table(rapply(ll,I))

Location_123 Location_321 Location_345     Time_321     Time_456     Time_789      Type_12      Type_32 
           3            3            3            2            2            2            2            2 

dat试试这个
lapply2
lappy
类似,只是它是后面的结果。我们拆分字符串参数并将结果放入
s
。然后我们计算一个新的数据帧
dat2
,每个ID有一行。对于样本数据,第1行有3个ID,第2行有2个ID,第3行有2个ID,因此
dat2
有3+2+2=7行。以类似的方式,我们分解
dat2
生成
dat3
。作为其中的一部分,我们使用
Straplyc
来简化提取所有事件的过程。最后,我们使用
aggregate
来计算结果

library(gsubfn)

lapply2 <- function(...) do.call("rbind", lapply(...))

s <- strsplit(dat$String, "&")

dat2 <- lapply2(1:nrow(dat), function(i) 
     data.frame(
            String = I(s[[i]]), 
            Value = dat$Value[i]
     )
)

dat3 <- lapply2(1:nrow(dat2), function(i) 
     data.frame(
            String = sub("=.*", "", dat2$String[i]), 
            Occurrence = strapplyc(dat2$String[i], "\\d+")[[1]], 
            Value = dat2$Value[i]
     )
)

ag <- aggregate(Value ~ String + Occurrence, dat3, sum)

试试这个
lapply2
lappy
类似,只是它是后面的结果。我们拆分字符串参数并将结果放入
s
。然后我们计算一个新的数据帧
dat2
,每个ID有一行。对于样本数据,第1行有3个ID,第2行有2个ID,第3行有2个ID,因此
dat2
有3+2+2=7行。以类似的方式,我们分解
dat2
生成
dat3
。作为其中的一部分,我们使用
Straplyc
来简化提取所有事件的过程。最后,我们使用
aggregate
来计算结果

library(gsubfn)

lapply2 <- function(...) do.call("rbind", lapply(...))

s <- strsplit(dat$String, "&")

dat2 <- lapply2(1:nrow(dat), function(i) 
     data.frame(
            String = I(s[[i]]), 
            Value = dat$Value[i]
     )
)

dat3 <- lapply2(1:nrow(dat2), function(i) 
     data.frame(
            String = sub("=.*", "", dat2$String[i]), 
            Occurrence = strapplyc(dat2$String[i], "\\d+")[[1]], 
            Value = dat2$Value[i]
     )
)

ag <- aggregate(Value ~ String + Occurrence, dat3, sum)

格罗森迪克的答案要好得多,但因为我已经开始研究解决方案,所以答案就在这里。这会粘在底端R上,并涉及一个长的
lappy
。假设您的数据名为“mydata”:

首先,用符号AND拆分“String”列

temp1 <- strsplit(mydata$String, "&")
结果如下所示:

ID String                                                    Value
1  LocationID=123,321,345&TimeID=456,321,789&TypeID=         100
2  LocationID=123,345&TimeID=&TypeID=A                       50
3  LocationID=123,321,345&TypeID=32                          120
temp2
#    ID Measure      Param Value
# 1   1     123 LocationID   100
# 2   1     321 LocationID   100
# 3   1     345 LocationID   100
# 4   1     456     TimeID   100
# 5   1     321     TimeID   100
# 6   1     789     TimeID   100
# 7   1      12     TypeID   100
# 8   1      32     TypeID   100
# 9   2     123 LocationID    50
# 10  2     345 LocationID    50
# 11  2     456     TimeID    50
# 12  2     321     TimeID    50
# 13  3     123 LocationID   120
# 14  3     321 LocationID   120
# 15  3     345 LocationID   120
# 16  3      32     TypeID   120
因此,现在我们可以很容易地在输出上使用
aggregate
,以获得以下结果:

aggregate(Value ~ Param + Measure, temp2, sum)
#        Param Measure Value
# 1     TypeID      12   100
# 2     TypeID      32   220
# 3 LocationID     123   270
# 4 LocationID     321   220
# 5     TimeID     321   150
# 6 LocationID     345   270
# 7     TimeID     456   150
# 8     TimeID     789   100

为方便起见,以下是数据前几行的
dput

mydata <- structure(list(ID = 1:3, 
                         String = c("LocationID=123,321,345&TimeID=456,321,789&TypeID=12,32",
                                    "LocationID=123,345&TimeID=456,321", 
                                    "LocationID=123,321,345&TypeID=32"), 
                         Value = c(100L, 50L, 120L)), 
                    .Names = c("ID", "String", "Value"), 
                    row.names = c(NA, -3L), 
                    class = "data.frame")

mydataG.Grothendieck的答案要好得多,但既然我已经开始研究一个解决方案,就在这里。这会粘在底端R上,并涉及一个长的
lappy
。假设您的数据名为“mydata”:

首先,用符号AND拆分“String”列

temp1 <- strsplit(mydata$String, "&")
结果如下所示:

ID String                                                    Value
1  LocationID=123,321,345&TimeID=456,321,789&TypeID=         100
2  LocationID=123,345&TimeID=&TypeID=A                       50
3  LocationID=123,321,345&TypeID=32                          120
temp2
#    ID Measure      Param Value
# 1   1     123 LocationID   100
# 2   1     321 LocationID   100
# 3   1     345 LocationID   100
# 4   1     456     TimeID   100
# 5   1     321     TimeID   100
# 6   1     789     TimeID   100
# 7   1      12     TypeID   100
# 8   1      32     TypeID   100
# 9   2     123 LocationID    50
# 10  2     345 LocationID    50
# 11  2     456     TimeID    50
# 12  2     321     TimeID    50
# 13  3     123 LocationID   120
# 14  3     321 LocationID   120
# 15  3     345 LocationID   120
# 16  3      32     TypeID   120
因此,现在我们可以很容易地在输出上使用
aggregate
,以获得以下结果:

aggregate(Value ~ Param + Measure, temp2, sum)
#        Param Measure Value
# 1     TypeID      12   100
# 2     TypeID      32   220
# 3 LocationID     123   270
# 4 LocationID     321   220
# 5     TimeID     321   150
# 6 LocationID     345   270
# 7     TimeID     456   150
# 8     TimeID     789   100

为方便起见,以下是数据前几行的
dput

mydata <- structure(list(ID = 1:3, 
                         String = c("LocationID=123,321,345&TimeID=456,321,789&TypeID=12,32",
                                    "LocationID=123,345&TimeID=456,321", 
                                    "LocationID=123,321,345&TypeID=32"), 
                         Value = c(100L, 50L, 120L)), 
                    .Names = c("ID", "String", "Value"), 
                    row.names = c(NA, -3L), 
                    class = "data.frame")

mydata非常感谢您,但是如果数据允许这种格式,您能进一步给我一些建议吗?ID字符串值1 LocationID=123321345&TimeID=456321789&TypeID=100 2 LocationID=123345&TimeID=&TypeID=a 50 3 LocationID=123321345&TypeID=32 120这是ID可以是字符串也可以是空的
dat2$String
对于空的右侧,将以
=
结尾,因此只需删除这些行:
dat2非常感谢,但是如果数据允许这种格式,您能进一步给我一些建议吗?ID字符串值1 LocationID=123321345&TimeID=456321789&TypeID=100 2 LocationID=123345&TimeID=&TypeID=a 50 3 LocationID=123321345&TypeID=32 120这是ID可以是字符串也可以是空的
dat2$String
对于空的右侧,将以
=
结尾,因此只需删除这些行:
dat2非常感谢!最后,我使用了您的建议,因为它更容易修改以解决我进一步的数据需求,再次感谢!谢谢!最后,我使用了您的建议,因为它更容易修改以解决我进一步的数据需求,再次感谢!