পাইথন পান্ডাগুলি সদৃশ কলামগুলি সরিয়ে দেয়


125

ডেটাফ্রেম থেকে সদৃশ কলামগুলি সরানোর সহজতম উপায় কী?

আমি একটি পাঠ্য ফাইলটি পড়ছি যার মাধ্যমে নকল কলাম রয়েছে:

import pandas as pd

df=pd.read_table(fname)

কলামের নামগুলি হ'ল:

Time, Time Relative, N2, Time, Time Relative, H2, etc...

সমস্ত সময় এবং সময় সম্পর্কিত কলামগুলিতে একই ডেটা থাকে। আমি চাই:

Time, Time Relative, N2, H2

ড্রপ, মুছে ফেলা ইত্যাদিতে আমার সমস্ত প্রচেষ্টা যেমন:

df=df.T.drop_duplicates().T

অনন্য মূল্যবান সূচক ত্রুটির ফলাফল:

Reindexing only valid with uniquely valued index objects

পান্ডস নুব হওয়ার জন্য দুঃখিত কোন পরামর্শ প্রশংসা হবে.


অতিরিক্ত তথ্য

পান্ডাস সংস্করণ: 0.9.0
পাইথন সংস্করণ: 2.7.3
উইন্ডোজ 7
(পাইথোনक्सी ২.xy.৩.০ এর মাধ্যমে ইনস্টল করা)

ডেটা ফাইল (দ্রষ্টব্য: আসল ফাইলে, কলামগুলি ট্যাব দ্বারা পৃথক করা হয়, এখানে সেগুলি 4 টি স্পেস দ্বারা পৃথক করা হয়েছে):

Time    Time Relative [s]    N2[%]    Time    Time Relative [s]    H2[ppm]
2/12/2013 9:20:55 AM    6.177    9.99268e+001    2/12/2013 9:20:55 AM    6.177    3.216293e-005    
2/12/2013 9:21:06 AM    17.689    9.99296e+001    2/12/2013 9:21:06 AM    17.689    3.841667e-005    
2/12/2013 9:21:18 AM    29.186    9.992954e+001    2/12/2013 9:21:18 AM    29.186    3.880365e-005    
... etc ...
2/12/2013 2:12:44 PM    17515.269    9.991756+001    2/12/2013 2:12:44 PM    17515.269    2.800279e-005    
2/12/2013 2:12:55 PM    17526.769    9.991754e+001    2/12/2013 2:12:55 PM    17526.769    2.880386e-005
2/12/2013 2:13:07 PM    17538.273    9.991797e+001    2/12/2013 2:13:07 PM    17538.273    3.131447e-005

আপনার কাছে পান্ডার কোন সংস্করণ রয়েছে? ( import pandas as pd; pd.__version__ )
beardc

1
@ বার্ডজাগুআরআইভি, আমি প্যান্ডাস সংস্করণ ০.৯.০ ব্যবহার করছি
17:25 এ 17:25

আপনি 0.10 এ আপগ্রেড করার চেষ্টা করতে পারেন। আমার সংস্করণটি কলামগুলি অনন্য করে তোলে read_tableযেমন আমি তৈরি করেছি for
beardc

সাবধান থাকুন যে df = df.T.DP_dپلকেট ()। টি কলামের নাম বিবেচনা করে না। আপনার যদি একই ডেটা সহ আলাদা আলাদা আলাদা নাম সহ দুটি কলাম থাকে তবে একটি ভুল করে ফেলে দেওয়া হবে।
জয়লভ

উত্তর:


390

সমস্যার একটি লাইন সমাধান রয়েছে। এটি প্রয়োগ হয় যদি কিছু কলামের নাম নকল হয়ে থাকে এবং আপনি সেগুলি মুছতে চান:

df = df.loc[:,~df.columns.duplicated()]

কিভাবে এটা কাজ করে:

ধরুন ডেটা ফ্রেমের কলামগুলি হল ['alpha','beta','alpha']

df.columns.duplicated()একটি বুলিয়ান অ্যারে প্রদান করে: একটি Trueবা Falseপ্রতিটি কলামের জন্য। যদি এটি হয় Falseতবে কলামের নামটি সেই বিন্দু পর্যন্ত অনন্য, যদি এটি হয় Trueতবে কলামের নামটি আগে নকল করা হবে। উদাহরণস্বরূপ, প্রদত্ত উদাহরণটি ব্যবহার করে, প্রত্যাবর্তিত মানটি হবে [False,False,True]

Pandasবুলিয়ান মানগুলি ব্যবহার করে একজনকে সূচকে অনুমতি দেয় যার মাধ্যমে এটি কেবলমাত্র Trueমানগুলি নির্বাচন করে । যেহেতু আমরা অনুলিপি করা কলামগুলি রাখতে চাই, আমাদের উপরের বুলিয়ান অ্যারে উল্টাতে হবে (অর্থাত্ [True, True, False] = ~[False,False,True])

অবশেষে, df.loc[:,[True,True,False]]পূর্বোক্ত সূচকগুলির ক্ষমতা ব্যবহার করে কেবল নন-অনুলিপি করা কলামগুলি নির্বাচন করে।

নোট : উপরে শুধুমাত্র চেক কলাম নাম, না কলাম মান।


16
একটি আদর্শ উত্তর কেবল নাম নয়, নকল মানগুলির জন্যও কাজ করবে।
গ্রিমস্পেকার

7
@ গ্রিমস্কুয়েকার: মানগুলি নকল হয়েছে কিনা তা আপনি যদি বিবেচনা করতে চান তবে আপনি এমন কিছু চান df.T.drop_duplicates().T
জন জুইঙ্ক

3
এখন পর্যন্ত সবচেয়ে দ্রুত সমাধান
এথোসিভ

2
@ বৈদিতাস আইভাকা দয়া করে এই প্রশ্নের
জিন বারিনস্কি

2
@ জনজিউইনক: এটি কেবল ছোট ডেটাফ্রেমের জন্য কাজ করে, কারণ আপনার কাছে থাকা কলামগুলির সংখ্যার সীমা রয়েছে। আমার জন্য এটি উদাহরণস্বরূপ 100,000 সারি সহ একটি ডেটাফ্রেমের জন্য ব্যর্থ হয়েছিল, কারণ এটি স্থানান্তরিত হওয়ার পরে 100,000 কলাম দেয়, যা সম্ভব নয়
ইয়েলকো ভ্যান ভিলেট

40

দেখে মনে হচ্ছে আপনি ইতিমধ্যে অনন্য কলামের নাম জানেন। যদি এটি হয়, তাহলে df = df['Time', 'Time Relative', 'N2']কাজ করবে।

যদি তা না হয় তবে আপনার সমাধানটি কাজ করা উচিত:

In [101]: vals = np.random.randint(0,20, (4,3))
          vals
Out[101]:
array([[ 3, 13,  0],
       [ 1, 15, 14],
       [14, 19, 14],
       [19,  5,  1]])

In [106]: df = pd.DataFrame(np.hstack([vals, vals]), columns=['Time', 'H1', 'N2', 'Time Relative', 'N2', 'Time'] )
          df
Out[106]:
   Time  H1  N2  Time Relative  N2  Time
0     3  13   0              3  13     0
1     1  15  14              1  15    14
2    14  19  14             14  19    14
3    19   5   1             19   5     1

In [107]: df.T.drop_duplicates().T
Out[107]:
   Time  H1  N2
0     3  13   0
1     1  15  14
2    14  19  14
3    19   5   1

আপনার কাছে সম্ভবত আপনার ডেটার সাথে নির্দিষ্ট কিছু রয়েছে যা এলোমেলো করছে। আপনি আমাদের ডেটা সম্পর্কে আরও কিছু বিবরণ দিতে পারলে আমরা আরও সহায়তা দিতে পারি।

সম্পাদনা: অ্যান্ডি বলেছিলেন, সমস্যাটি সম্ভবত নকল কলামের শিরোনাম নিয়ে।

একটি নমুনা টেবিল ফাইলের জন্য 'dummy.csv' আমি তৈরি করেছি:

Time    H1  N2  Time    N2  Time Relative
3   13  13  3   13  0
1   15  15  1   15  14
14  19  19  14  19  14
19  5   5   19  5   1

ব্যবহার read_tableঅনন্য কলাম দেয় এবং সঠিকভাবে কাজ করে:

In [151]: df2 = pd.read_table('dummy.csv')
          df2
Out[151]:
         Time  H1  N2  Time.1  N2.1  Time Relative
      0     3  13  13       3    13              0
      1     1  15  15       1    15             14
      2    14  19  19      14    19             14
      3    19   5   5      19     5              1
In [152]: df2.T.drop_duplicates().T
Out[152]:
             Time  H1  Time Relative
          0     3  13              0
          1     1  15             14
          2    14  19             14
          3    19   5              1  

যদি আপনার সংস্করণটি আপনাকে অনুমতি না দেয় তবে আপনি এগুলি অনন্য করার জন্য একটি সমাধানকে একত্রে হ্যাক করতে পারেন:

In [169]: df2 = pd.read_table('dummy.csv', header=None)
          df2
Out[169]:
              0   1   2     3   4              5
        0  Time  H1  N2  Time  N2  Time Relative
        1     3  13  13     3  13              0
        2     1  15  15     1  15             14
        3    14  19  19    14  19             14
        4    19   5   5    19   5              1
In [171]: from collections import defaultdict
          col_counts = defaultdict(int)
          col_ix = df2.first_valid_index()
In [172]: cols = []
          for col in df2.ix[col_ix]:
              cnt = col_counts[col]
              col_counts[col] += 1
              suf = '_' + str(cnt) if cnt else ''
              cols.append(col + suf)
          cols
Out[172]:
          ['Time', 'H1', 'N2', 'Time_1', 'N2_1', 'Time Relative']
In [174]: df2.columns = cols
          df2 = df2.drop([col_ix])
In [177]: df2
Out[177]:
          Time  H1  N2 Time_1 N2_1 Time Relative
        1    3  13  13      3   13             0
        2    1  15  15      1   15            14
        3   14  19  19     14   19            14
        4   19   5   5     19    5             1
In [178]: df2.T.drop_duplicates().T
Out[178]:
          Time  H1 Time Relative
        1    3  13             0
        2    1  15            14
        3   14  19            14
        4   19   5             1 

5
দুর্ভাগ্যক্রমে df['Time']সমস্ত টাইম সিরিজ নির্বাচন করে (যেমন একটি ডেটাফ্রেম রিটার্ন করে) এবং df['Time', ..]এটি পুরো ডেটা ফ্রেমকে ফিরিয়ে দেবে।
অ্যান্ডি হেডেন

হ্যাঁ, এটি বেশ ক্লান্তিকর ... আশা করি এটি কেবল একটি সংস্করণের পার্থক্য।
beardc

2
ডাবল ট্রান্সপোজ ব্যবহারের ফলে সংখ্যার ধরণের জিনিসগুলিকে মিশ্রিত প্রকারের সাথে ডিএফ-র ক্ষেত্রে রূপান্তর করার মতো অযৌক্তিক পার্শ্ব প্রতিক্রিয়া হতে পারে। দেখুন: stackoverflow.com/questions/24682396/...
Petergavinkin

এই সমাধানটি আমাকে বড় ডেটাফ্রেমে সমস্যা দেয়: RecursionError: maximum recursion depth exceeded
স্কট

বড় ডেটা ফ্রেমের
কুশ প্যাটেল

13

বড় ডেটা ফ্রেমের জন্য ট্রান্সপোসিং অকার্যকর। এখানে একটি বিকল্প:

def duplicate_columns(frame):
    groups = frame.columns.to_series().groupby(frame.dtypes).groups
    dups = []
    for t, v in groups.items():
        dcols = frame[v].to_dict(orient="list")

        vs = dcols.values()
        ks = dcols.keys()
        lvs = len(vs)

        for i in range(lvs):
            for j in range(i+1,lvs):
                if vs[i] == vs[j]: 
                    dups.append(ks[i])
                    break

    return dups       

এটি এর মতো ব্যবহার করুন:

dups = duplicate_columns(frame)
frame = frame.drop(dups, axis=1)

সম্পাদন করা

একটি মেমরি দক্ষ সংস্করণ যা ন্যানদের সাথে অন্য কোনও মানের মতো আচরণ করে:

from pandas.core.common import array_equivalent

def duplicate_columns(frame):
    groups = frame.columns.to_series().groupby(frame.dtypes).groups
    dups = []

    for t, v in groups.items():

        cs = frame[v].columns
        vs = frame[v]
        lcs = len(cs)

        for i in range(lcs):
            ia = vs.iloc[:,i].values
            for j in range(i+1, lcs):
                ja = vs.iloc[:,j].values
                if array_equivalent(ia, ja):
                    dups.append(cs[i])
                    break

    return dups

3
একটি মোহন মত কাজ করে, খুব দক্ষ! my_df.T.drop_duplicates().Tবড় ডেটা ফ্রেম ব্যবহার করে হ্যাঙ্গ করা হবে।
উইল

1
সুন্দর সমাধান তবে 26 এপ্রিল, 2017 এ আমি পেয়েছি /usr/local/lib/python3.5/dist-packages/ipykernel_launcher.py:17: DeprecationWarning: 'pandas.core.common.array_equivalent' is deprecated and is no longer public API
জর্জ ফিশার

প্রতিস্থাপন if array_equivalent(ia, ja):সঙ্গে if np.array_equal(ia, ja):একই ফল বলে মনে হয় কিন্তু আমি পড়তে এটি Nans ভাল হ্যান্ডেল করা হয় না।
জর্জ ফিশার

@ জর্জিফিশার array_equivalentসম্ভবত কোনও পুরানো শাখায় পাবলিক রেপোতে এখনও অন্তর্নিহিত কোড উপলব্ধ?
কালু

@ কালু এখন একটি স্রোত আছে numpy.array_equiv; পান্ডাদের জন্য, আমি গিটহাবের আগের কোনও প্রকাশিত শাখা দেখতে পাচ্ছি না তবে দেখার pandas.core.commonমতো অন্যান্য জায়গাগুলি রয়েছে
জর্জ ফিশার

11

যদি আমি ভুল না হয়ে থাকি তবে ট্রান্সপোজ সমাধানের মেমোরি সমস্যা ছাড়াই এবং @ কালুর কার্যকারিতার চেয়ে কম লাইনের সাথে অনুরূপ নামযুক্ত কলামগুলির প্রথমটিকে রেখে, নিম্নলিখিতটি যা জিজ্ঞাসা করেছিল তা করে।

Cols = list(df.columns)
for i,item in enumerate(df.columns):
    if item in df.columns[:i]: Cols[i] = "toDROP"
df.columns = Cols
df = df.drop("toDROP",1)

আপনার সমাধানটি আমার ক্ষেত্রে কার্যকর হয় না, এটি আমাকে দেখায়: "ভ্যালুআরার: লেবেল ['toDROP'] অক্ষের মধ্যে নেই" শেষ লাইনটি কার্যকর করার পরে
নিউভালিউ

4

দেখে মনে হচ্ছে আপনি সঠিক পথে ছিলেন। আপনি যে ওয়ান-লাইনার সন্ধান করেছিলেন তা এখানে:

df.reset_index().T.drop_duplicates().T

তবে যেহেতু কোনও রেফারেন্সযুক্ত ত্রুটি বার্তা তৈরি করে এমন কোনও ডেটা ফ্রেম নেই Reindexing only valid with uniquely valued index objects, তাই সমস্যাটি কী সমাধান করবে ঠিক তা বলা শক্ত। যদি মূল সূচকটি পুনরুদ্ধার করা আপনার পক্ষে গুরুত্বপূর্ণ তবে এটি করুন:

original_index = df.index.names
df.reset_index().T.drop_duplicates().reset_index(original_index).T

0

প্রথম পদক্ষেপ: - প্রথম সারিতে অর্থাত্ সমস্ত কলামগুলি সমস্ত নকল কলামগুলি মুছে ফেলুন Read

দ্বিতীয় পদক্ষেপ: - অবশেষে কেবল সেই কলামগুলিই পড়ুন।

cols = pd.read_csv("file.csv", header=None, nrows=1).iloc[0].drop_duplicates()
df = pd.read_csv("file.csv", usecols=cols)

0

আমি এই সমস্যায় পড়েছিলাম যেখানে প্রথম উত্তরের সরবরাহ করা একটি লাইনার ভালভাবে কাজ করেছিল। যাইহোক, আমার অতিরিক্ত জটিলতা ছিল যেখানে কলামের দ্বিতীয় অনুলিপিতে সমস্ত ডেটা ছিল। প্রথম কপি না।

সমাধানটি ছিল নেগেশন অপারেটর টগল করে একটি ডেটা ফ্রেমকে বিভক্ত করে দুটি ডেটা ফ্রেম তৈরি করা। আমার কাছে দুটি ডেটা ফ্রেম হয়ে গেলে আমি ব্যবহার করে একটি জয়েন স্টেটমেন্ট চালিয়েছিলাম lsuffix। এইভাবে, আমি তখন তথ্য ছাড়াই কলামটি উল্লেখ করতে এবং মুছতে পারি।

- ই


0

নীচের উপায়টি মূলত ডেটাফ্রেম তৈরিতে কী ভুল হচ্ছে তা পর্যালোচনা করতে ডুপ কলামগুলি সনাক্ত করবে।

dupes = pd.DataFrame(df.columns)
dupes[dupes.duplicated()]

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