একটি কার্যকর সিএসভিতে কিছুটা দুর্বল সীমিত ডেটা ম্যানিপুলেট করুন


13

আকারে আমার কিছু আউটপুট রয়েছে:

count  id     type
588    10 |    3
 10    12 |    3
883    14 |    3
 98    17 |    3
 17    18 |    1
77598    18 |    3
10000    21 |    3
17892     2 |    3
20000    23 |    3
 63    27 |    3
  6     3 |    3
 2446    35 |    3
 14    4 |    3
 15     4 |    1
253     4 |    2
19857     4 |    3
 1000     5 |    3
...

যা বেশ অগোছালো এবং একটি সিএসভি পর্যন্ত পরিষ্কার করা দরকার তাই আমি এটির জন্য একটি প্রজেক্ট ম্যানেজারকে উপহার দিতে পারি তার জন্য স্প্রেডশীটটি এর থেকে দূরে।

সমস্যার মূলটি হ'ল: এটির আউটপুট আমার হওয়া দরকার:

আইডি, যোগ_ফোঁটা_প্রকার_1, যোগ_আর_প্রকার 3, যোগ_আর_ধর্ম টাইপ 14

এর একটি উদাহরণ আইডি "4":

14    4 |    3
 15     4 |    1
253     4 |    2
19857     4 |    3

পরিবর্তে এটি হওয়া উচিত:

4,15,253,19871

দুর্ভাগ্যক্রমে আমি এই ধরণের জিনিসটিতে বেশ জঞ্জাল পেয়েছি, আমি সমস্ত লাইন পরিষ্কার করে সিএসভিতে সজ্জিত করতে পেরেছি তবে আমি সারিগুলি প্রতিলিপি এবং দলবদ্ধ করতে সক্ষম হইনি। এই মুহূর্তে আমার কাছে এটি রয়েছে:

awk 'BEGIN{OFS=",";} {split($line, part, " "); print part[1],part[2],part[4]}' | awk '{ gsub (" ", "", $0); print}'

তবে যা কিছু করা হয় তা হ'ল আবর্জনা চরিত্রগুলি পরিষ্কার করে আবার সারিগুলি মুদ্রণ করা।

উপরে বর্ণিত আউটপুটটিতে সারিগুলি ম্যাসেজ করার সর্বোত্তম উপায় কী?


আপনি কি একসাথে গণনাগুলি যোগ করতে চান?
hjk

উত্তর:


12

এটি করার একটি উপায় হ্যাশে সমস্ত কিছু রাখা।

# put values into a hash based on the id and tag
awk 'NR>1{n[$2","$4]+=$1}
END{
    # merge the same ids on the one line
    for(i in n){
        id=i;
        sub(/,.*/,"",id);
        a[id]=a[id]","n[i];
    }
    # print everyhing
    for(i in a){
        print i""a[i];
    }
}'

সম্পাদনা: আমার প্রথম উত্তরটি সঠিকভাবে প্রশ্নের উত্তর দেয়নি


হ্যাঁ, এই কৌশলটি খুব সুন্দরভাবে করেছে। ধন্যবাদ! কেবলমাত্র আমি আইডি থেকে খালি থাকা এবং এইভাবে সিএসভি গোলযোগের জন্য কিছু প্রকারের জন্য অ্যাকাউন্ট করি না, তবে আমি সেই সামান্য
পল

হয়তো যোগ @Paul NF<4{$4="no_type";}শুরুতে
DarkHeart

11

উদ্ধারের জন্য পার্ল:

#!/usr/bin/perl
use warnings;
use strict;
use feature qw{ say };

<>;  # Skip the header.

my %sum;
my %types;
while (<>) {
    my ($count, $id, $type) = grep length, split '[\s|]+';
    $sum{$id}{$type} += $count;
    $types{$type} = 1;
}

say join ',', 'id', sort keys %types;
for my $id (sort { $a <=> $b } keys %sum) {
    say join ',', $id, map $_ // q(), @{ $sum{$id} }{ sort keys %types };
}

এটি দুটি টেবিল রাখে, প্রকারের সারণী এবং আইডির টেবিল রাখে। প্রতিটি আইডির জন্য, এটি প্রতি প্রকারের সমষ্টি সঞ্চয় করে।


5

জিএনইউ দাতামাশ যদি আপনার জন্য একটি বিকল্প হয় তবে তা

awk 'NR>1 {print $1, $2, $4}' OFS=, file | datamash -t, -s --filler=0 crosstab 2,3 sum 1
,1,2,3
10,0,0,588
12,0,0,10
14,0,0,883
17,0,0,98
18,17,0,77598
2,0,0,17892
21,0,0,10000
23,0,0,20000
27,0,0,63
3,0,0,6
35,0,0,2446
4,15,253,19871
5,0,0,1000

4

পাইথন (এবং pandasবিশেষত গ্রন্থাগার এই ধরণের কাজের জন্য খুব উপযুক্ত

data = """count  id     type
588    10 |    3
 10    12 |    3
883    14 |    3
 98    17 |    3
 17    18 |    1
77598    18 |    3
10000    21 |    3
17892     2 |    3
20000    23 |    3
 63    27 |    3
  6     3 |    3
 2446    35 |    3
 14    4 |    3
 15     4 |    1
253     4 |    2
19857     4 |    3
 1000     5 |    3"""

import pandas as pd
from io import StringIO # to read from string, not needed to read from file

df = pd.read_csv(StringIO(data), sep=sep='\s+\|?\s*', index_col=None, engine='python')

এটি সিএসভি ডেটা পড়ে a pandas DataFrame

    count  id  type
0     588  10     3
1      10  12     3
2     883  14     3
3      98  17     3
4      17  18     1
5   77598  18     3
6   10000  21     3
7   17892   2     3
8   20000  23     3
9      63  27     3
10      6   3     3
11   2446  35     3
12     14   4     3
13     15   4     1
14    253   4     2
15  19857   4     3
16   1000   5     3

তারপরে আমরা এই ডেটা দ্বারা গ্রুপ করবid , এবং কলামের যোগফল নিয়ে যাবcount

df_sum = df.groupby(('type', 'id'))['count'].sum().unstack('type').fillna(0)

unstack Reshapes এই আইডি কলাম এর সরাতে, এবং fillna'0' র খালি ক্ষেত্র পূরণ

df_sum.to_csv()

এই ফিরে আসে

id,1,2,3
2,0.0,0.0,17892.0
3,0.0,0.0,6.0
4,15.0,253.0,19871.0
5,0.0,0.0,1000.0
10,0.0,0.0,588.0
12,0.0,0.0,10.0
14,0.0,0.0,883.0
17,0.0,0.0,98.0
18,17.0,0.0,77598.0
21,0.0,0.0,10000.0
23,0.0,0.0,20000.0
27,0.0,0.0,63.0
35,0.0,0.0,2446.0

কারণ dataframe অনুপস্থিত তথ্য (খালি আইডি টাইপ সমন্বয়), পান্ডাস রূপান্তরগুলির রয়েছে ints করা float(অভ্যন্তরীণ ক্রিয়াকাণ্ড সীমাবদ্ধতা) আপনি কি জানেন ইনপুট শুধুমাত্র কোন int হতে wil থাকে, তাহলে আপনি পরিবর্তন হতে পারে আগামী-টু শেষ লাইনdf_sum = df.groupby(('type', 'id'))['count'].sum().unstack('type').fillna(0).astype(int)


1
আপনার প্রদত্ত কোডটি কী করে তা আপনার ব্যাখ্যা করা উচিত, সুতরাং এই নির্দিষ্ট ব্যক্তির চেয়ে এই পোস্টটি দেখার প্রত্যেকের পক্ষে এটি সহায়ক।
মনিকার লসুইট

এটা কি পরিষ্কার? আমি পৃথককারীটির জন্য রেজেেক্সটিও সংশোধন করেছি
মার্টেন ফ্যাব্রি

আমার কাছে ভালই মনে হচ্ছে. একটি ব্যাখ্যা যোগ করার জন্য ধন্যবাদ!
মনিকা'র মোকদ্দমা

3

আপনি সিএসভি ফাইলটি লুপ করতে এবং পথে চলার সময় একটি হ্যাশে উপযুক্ত ধরণের যোগফল সংগ্রহ করতে পার্ল ব্যবহার করতে পারেন। এবং শেষে, প্রতিটি আইডির জন্য সংগৃহীত তথ্য প্রদর্শন করুন।

তথ্য কাঠামো

%h = (
   ID1    =>  [ sum_of_type1, sum_of_type2, sum_of_type3 ],
   ...
)

এটি নীচের কোডটি অনুধাবন করতে সহায়তা করে:

পার্ল

perl -wMstrict -Mvars='*h' -F'\s+|\|' -lane '
   $, = chr 44, next if $. == 1;

   my($count, $id, $type) = grep /./, @F;
   $h{ $id }[ $type-1 ] += $count}{
   print $_, map { $_ || 0 } @{ $h{$_} } for sort { $a <=> $b } keys %h
' yourcsvfile

আউটপুট

2,0,0,17892
3,0,0,6
4,15,253,19871
5,0,0,1000
...

1

আমার গ্রহণ, অন্যদের থেকে খুব আলাদা নয়। GNU awk ব্যবহার করে যার অ্যারে রয়েছে

gawk '
    NR == 1 {next}
    {count[$2][$4] += $1}
    END {
        for (id in count) {
            printf "%d", id
            for (type=1; type<=3; type++) {
                # add zero to coerce possible empty string into a number 
                printf ",%d", 0 + count[id][type]
            }
            print ""        # adds the newline for this line
        }
    }
' file

আউটপুট

2,0,0,17892
3,0,0,6
4,15,253,19871
5,0,0,1000
10,0,0,588
12,0,0,10
14,0,0,883
17,0,0,98
18,17,0,77598
21,0,0,10000
23,0,0,20000
27,0,0,63
35,0,0,2446

0

আপনি এই আইডিটি কলামের উপর ভিত্তি করে মানগুলি যোগ করতে এই কোডটি ব্যবহার করতে পারেন,

আমি আপনার কোড পরে একটি বিশ্রী বিবৃতি যোগ করেছি

awk 'BEGIN{OFS=",";} {split($line, part, " "); print part[1],part[2],part[4]}' abcd | awk '{ gsub (" ", "", $0); print}' | awk 'BEGIN{FS=OFS=SUBSEP=","}{arr[$2,$3]+=$1;}END{for ( i in arr ) print i,arr[i];}'

এটি দিয়ে এগিয়ে যান ...

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