অক্ষর কলামগুলি বিভক্ত করুন এবং স্ট্রিংয়ের ক্ষেত্রে ক্ষেত্রের নাম পান


11

আমাকে এমন একটি কলাম বিভক্ত করতে হবে যাতে বিভিন্ন কলামে তথ্য রয়েছে।
আমি ব্যবহার করব tstrsplitতবে একই ধরণের তথ্য সারিগুলির মধ্যে একই ক্রমে নয় এবং ভেরিয়েবলের মধ্যে নতুন কলামের নাম বের করতে হবে। জেনে রাখা গুরুত্বপূর্ণ: তথ্যের অনেকগুলি অংশ থাকতে পারে (ক্ষেত্রগুলি নতুন ভেরিয়েবল হয়ে উঠতে পারে) এবং আমি সেগুলি সব জানি না, তাই আমি "ফিল্ড বাই ফিল্ড" সমাধান চাই না।

নীচে আমার যা আছে তার উদাহরণ দেওয়া হল:

library(data.table)

myDT <- structure(list(chr = c("chr1", "chr2", "chr4"), pos = c(123L,
                  435L, 120L), info = c("type=3;end=4", "end=6", "end=5;pos=TRUE;type=2"
                  )), class = c("data.table", "data.frame"), row.names = c(NA,-3L))

#    chr pos                  info
#1: chr1 123          type=3;end=4
#2: chr2 435                 end=6
#3: chr4 120 end=5;pos=TRUE;type=2

এবং আমি পেতে চাই:

#    chr pos end  pos type
#1: chr1 123   4 <NA>    3
#2: chr2 435   6 <NA> <NA>
#3: chr4 120   5 TRUE    2

এটি পেতে একটি সহজ সরল উপায় প্রশংসা হবে! ( দ্রষ্টব্য: আমি কোনও dplyr / পরিপাটি পথে যেতে রাজি নই )

উত্তর:


5

ব্যবহার regexএবং stringiপ্যাকেজ:

setDT(myDT) # After creating data.table from structure()

library(stringi)

fields <- unique(unlist(stri_extract_all(regex = "[a-z]+(?==)", myDT$info)))
patterns <- sprintf("(?<=%s=)[^;]+", fields)
myDT[, (fields) := lapply(patterns, function(x) stri_extract(regex = x, info))]
myDT[, !"info"]

    chr  pos type end
1: chr1 <NA>    3   4
2: chr2 <NA> <NA>   6
3: chr4 TRUE    2   5

সম্পাদনা করুন: সঠিক ধরণের জন্য মনে হয় (?) type.convert()ব্যবহার করা যেতে পারে:

myDT[, (fields) := lapply(patterns, function(x) type.convert(stri_extract(regex = x, info), as.is = TRUE))]

আমি একটি দীর্ঘ দীর্ঘ সতর্কতা পেয়েছি "" অবৈধ। অভ্যন্তরীণ.সেফেরফ ডেটাটির একটি (অগভীর) অনুলিপিটি সনাক্ত করে সনাক্ত এবং ঠিক করা হয়েছে ... "
মুডি_মডস্কিপার

এছাড়াও টাইপ করুন এবং শেষ এখানে অক্ষর রয়েছে, এটি প্রত্যাশিত কিনা তা নিশ্চিত নন
মুডি_মডসকিপার

1
@ মুডি_মদস্কিপার মন্তব্য করার জন্য ধন্যবাদ। (1) (এই সতর্কতাটি হ'ল (আমার মনে হয়) ডেটা তৈরি করার কারণে তৈরি হয়েছে by structure()এই সমস্যাটি এড়াতে আমি উত্তর আপডেট করেছি (২) এগুলি উদ্দেশ্য অনুসারে চরিত্রগুলি ... আমি অনুভব করেছি সঠিকভাবে পার্স করা খুব কঠিন হবে এবং একটি পৃথক প্রশ্ন It মনে হচ্ছে আপনি নিজের উত্তরের
মধ্যেই

4

আমি অনুমান করছি যে আপনার ডেটা একটি ভিসিএফ ফাইল থেকে আসছে , যদি তাই হয় তবে এই জাতীয় সমস্যার জন্য একটি উত্সর্গীকৃত সরঞ্জাম রয়েছে - বিসিএফটিউলস

আসুন পরীক্ষার জন্য উদাহরণস্বরূপ ভিসিএফ ফাইল তৈরি করুন:

# subset some data from 1000genomes data
tabix -h ftp://ftp-trace.ncbi.nih.gov/1000genomes/ftp/release/20100804/ALL.2of4intersection.20100804.genotypes.vcf.gz 17:1471000-1472000 > myFile.vcf
# zip it and index:
bgzip -c myFile.vcf > myFile.vcf.gz
tabix -p vcf myFile.vcf.gz

এখন আমরা বিসিএফটিউল ব্যবহার করতে পারি । এখানে উদাহরণ হিসাবে আমরা INFO কলাম থেকে এএফ এবং ডিপি উপসেট করে দিচ্ছি :

bcftools query -f '%CHROM %POS %INFO/AF %INFO/DP \n' myFile.vcf.gz 
17  1471199  1916 0.088
17  1471538  2445 0.016
17  1471611  2733 0.239
17  1471623  2815 0.003
17  1471946  1608 0.007
17  1471959  1612 0.014
17  1471975  1610 0.179

আরও ক্যোয়ারী বিকল্পের জন্য ম্যানুয়ালটি দেখুন ।


3

আমরা ";"তারপরে বিস্তৃত করতে পারতাম বিস্তৃত "="থেকে দীর্ঘতর আকার পুনরায় আকার দিতে, তারপরে আবার বিভাজন , তারপরে দীর্ঘ-থেকে-প্রশস্ত আকারে পুনরায় আকার:

dcast(
  melt(dt[,  paste0("col", 1:3) := tstrsplit(info, split = ";") ],
       id.vars = c("chr", "pos", "info"))[, -c("info", "variable")][
         ,c("x1", "x2") := tstrsplit(value, split = "=")][
           ,value := NULL][ !is.na(x1), ],
  chr + pos ~ x1, value.var = "x2")

#     chr pos end  pos type
# 1: chr1 123   4 <NA>    3
# 2: chr2 435   6 <NA> <NA>
# 3: chr4 120   5 TRUE    2

একটি উন্নত / আরও পঠনযোগ্য সংস্করণ:

dt[, paste0("col", 1:3) := tstrsplit(info, split = ";")
   ][, melt(.SD, id.vars = c("chr", "pos", "info"), na.rm = TRUE)
     ][, -c("info", "variable")
       ][, c("x1", "x2") := tstrsplit(value, split = "=")
         ][, dcast(.SD, chr + pos ~ x1, value.var = "x2")]

@ জাপ আপনাকে ধন্যবাদ, আমি জানতাম জিনিসগুলিতে শিকল দেওয়ার আরও ভাল ডিটি উপায় ছিল।
zx8754

3

আপাতত, আমি নিম্নলিখিত কোডটি দিয়ে যা চাই তা পেতে সক্ষম হয়েছি:

newDT <- reshape(splitstackshape::cSplit(myDT, "info", sep=";", "long")[, 
                  c(.SD, tstrsplit(info, "="))], 
                 idvar=c("chr", "pos"), direction="wide", timevar="V4", drop="info")
setnames(newDT, sub("V5\\.", "", names(newDT)))

newDT
#    chr pos type end  pos
#1: chr1 123    3   4 <NA>
#2: chr2 435 <NA>   6 <NA>
#3: chr4 120    2   5 TRUE

উপরের লাইনগুলিকে উন্নত করার জন্য দুটি বিকল্প, @ A5C1D2H2I1M1N2O1R2T1 (যিনি তাদের মন্তব্যে দিয়েছেন): ধন্যবাদ

। এর cSplitআগে ডাবল সহ dcast:

cSplit(cSplit(myDT, "info", ";", "long"), "info", "=")[, dcast(.SD, chr + pos ~ info_1, value.var = "info_2")]

। এর সাথে cSplit/ trstrplitএবং এর dcastপরিবর্তে reshape:

cSplit(myDT, "info", ";", "long")[, c("t1", "t2") := tstrsplit(info, "=", fixed = TRUE)][, dcast(.SD, chr + pos ~ t1, value.var = "t2")]

1
আমি একটা ডাবল করতে চাই cSplitভালো: cSplit(cSplit(myDT, "info", ";", "long"), "info", "=")[, dcast(.SD, chr + pos ~ info_1, value.var = "info_2")]
A5C1D2H2I1M1N2O1R2T1

1
অথবা, একই ধারণা: cSplitদ্বারা অনুসরণ tstrsplit, দ্বারা অনুসরণ dcast: cSplit(myDT, "info", ";", "long")[, c("t1", "t2") := tstrsplit(info, "=", fixed = TRUE)][, dcast(.SD, chr + pos ~ t1, value.var = "t2")]
A5C1D2H2I1M1N2O1R2T1

@ A5C1D2H2I1M1N2O1R2T1 অনেক ধন্যবাদ! দু'জনই দুর্দান্ত, ডাবল cSplitবিকল্পের জন্য একটি বিশেষ সহ :-)
ক্যাথ

2

আমি এটি কীভাবে করব তা এখানে:

library(data.table)

myDT <- structure(list(chr = c("chr1", "chr2", "chr4"), pos = c(123L,
                                                                435L, 120L), info = c("type=3;end=4", "end=6", "end=5;pos=TRUE;type=2"
                                                                )), class = c("data.table", "data.frame"), row.names = c(NA,-3L))

R_strings <- paste0("list(", chartr(";", ",", myDT$info),")")
lists <- lapply(parse(text=R_strings),eval)
myDT[,info:=NULL]
myDT <- cbind(myDT,rbindlist(lists, fill = TRUE))
myDT
#>     chr pos type end  pos
#> 1: chr1 123    3   4   NA
#> 2: chr2 435   NA   6   NA
#> 3: chr4 120    2   5 TRUE

2019-11-29 তারিখে ডিপেক্স প্যাকেজ (v0.3.0) দ্বারা তৈরি


আমি পরিবর্তন করার প্রয়োজন পাই না ";" "," এবং পছন্দ করে না eval(parse(text=...))... তবে আপনার উত্তরের জন্য ধন্যবাদ
ক্যাথ

1
আমি ব্যক্তিগত স্বাদের সাথে তর্ক করতে পারি না তবে parseএকটি খারাপ প্রতিনিধি আছে কারণ এটি প্রায়শই ভুল কারণে ব্যবহৃত হয়, স্ট্রিং থেকে কোডে যাওয়ার জন্য এখানে যথাযথভাবে এর উপযুক্ত ব্যবহারের মামলা রয়েছে case আপনি পাঠ্য ফর্ম্যাট করেছেন, কিন্তু আর এর জন্য ফর্ম্যাট করেননি এবং আপনি তালিকার নাম দিয়েছেন, সুতরাং আমার প্রথম লাইনটি "ক; বি" কে "তালিকার (ক, খ)" এ পরিবর্তন করে একটি আর তালিকার জন্য কোড তৈরি করে। তারপরে আমরা এটিকে মূল্যায়ন করব এবং এর থেকে একটি টেবিল তৈরি করব।
মুডি_ মুডস্কিপার

1

আপনি subপ্রতিটি কাঙ্ক্ষিত নিষ্ক্রিয় ক্ষেত্রের জন্য পৃথক কলগুলি ব্যবহার করতে পারেন , যেমন type:

myDT$type <- sub("^.*\\btype=([^;]+)\\b.*$", "\\1", myDT$info)

যে সমস্ত ফাইল ফাইল হবে তা আমি জানি না এবং এগুলি অনেক কিছু হতে পারে তাই এটি কোনও বিকল্প নয়
ক্যাথ

1
যথেষ্ট ফর্সা; আমি এই উত্তরটি পোস্ট করার সময় এটি জানতাম না।
টিম বিগলেইসেন

আমি এটি যুক্ত করব (বিটিডব্লিউ আপনি পছন্দসই আউটপুট দেবেন না, আপনার উত্তরটি কিছু লাইন মিস করেছে ...)
ক্যাথ
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.