Как я могу удалить столбцы nan, если значения являются строковыми / целочисленными dtypes одновременно?

#python #pandas

#python #панды

Вопрос:

У меня есть такие данные, как:

 In [1]: d = {'ID': [14, 14, 14, 14, 14, 14, 14, 15, 15], 
         'NAME': ['KWI', 'NED', 'RICK', 'NICH', 'DIONIC', 'RICHARD', 'ROCKY', 'CARLOS', 'SIDARTH'], 
         'ID_COUNTRY':[1, 2, 3,4,5,6,7,8,9], 
         'COUNTRY':['MEXICO', 'ITALY', 'CANADA', 'ENGLAND', 'GERMANY', 'UNITED STATES', 'JAPAN', 'SPAIN', 'BRAZIL'], 
         'ID_CITY':[np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan], 
         'CITY':[np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan], 
         'STATUS': ['OK', 'OK', 'OK', 'OK', 'OK', 'NOT', 'OK', 'NOT', 'OK']}
    df = pd.DataFrame(data=d)

Out[2]:
      ID       NAME      ID_COUNTRY     COUNTRY        ID_CITY     CITY     STATUS
0     14       KWI           1           MEXICO          NaN        NaN        OK
1     14       NED           2           ITALY           NaN        NaN        OK
2     14       RICK          3           CANADA          NaN        NaN        OK
3     14       NICH          4           ENGLAND         NaN        NaN       OK
4     14       DIONIC        5           GERMANY         NaN        NaN        OK 
5     14       RICHARD       6           UNITED STATES   NaN        NaN        NOT
6     14       ROCKY         7           JAPAN           NaN        NaN        OK
7     15       CARLOS        8           SPAIN           NaN        NaN        NOT
8     15       SIDHART       9           BRAZIL          NaN        NaN        OK
  

Затем мне нужно установить dtypes каждого столбца для будущего использования с помощью:

 df.iloc[:, [0, 2, 4]] = df.iloc[:, [0, 2, 4]].astype("Int64")
df.iloc[:, [1, 3, 5, 6]] = df.iloc[:, [1, 3, 5, 6]].astype("string")
  

После этого я хочу удалить столбцы, которые имеют полные nan значения, и получить имена столбцов, которые будут удалены для повторного перемещения в другой фрейм данных с такими же именами столбцов, как это:

  In [3]: d1 = {'ID': [14, 14, 14], 
         'NAME': ['KWI', 'NED', 'RICK'], 
         'ID_COUNTRY':[1, 2, 3], 
         'COUNTRY':['MEXICO', 'ITALY', 'CANADA'], 
         'ID_CITY':[20, 22, 24], 
         'CITY':['MX', 'AT', 'CA'], 
         'STATUS': ['OK', 'OK', 'OK']}
    df1 = pd.DataFrame(data=d1)
 Out [4]: 
      ID       NAME      ID_COUNTRY     COUNTRY        ID_CITY     CITY     STATUS
0     14       KWI           1           MEXICO          20        MX        OK
1     14       NED           2           ITALY           22        AT        OK
2     14       RICK          3           CANADA          24        CA        OK
  

Проблема здесь в том, когда я пытаюсь df['CITY'].isna() , потому что выдает мне False все значения в столбце. Я не понимаю, почему это дает мне это, и когда я пытаюсь, df['ID_CITY'].isna() это дает мне True . Я думаю , это потому , что одно есть Int64 , а другое object есть .
Примеры:

 In [5]: df4['ID_CITY'].isna()                       
Out[6]:                         
0    True                   
1    True
2    True                          
3    True
4    True
5    True
6    True
7    True
8    True
Name: ID_CITY, dtype: bool

In [7]: df4['CITY'].isna()
Out[8]:
0    False
1    False
2    False
3    False
4    False
5    False
6    False
7    False
8    False
Name: CITY, dtype: bool
  

После исправления того, что я упомянул ранее, желаемый результат для df и df1 будет:

 Out[9]:
      ID       NAME      ID_COUNTRY     COUNTRY          STATUS
0     14       KWI           1           MEXICO            OK
1     14       NED           2           ITALY             OK
2     14       RICK          3           CANADA            OK
3     14       NICH          4           ENGLAND           OK
4     14       DIONIC        5           GERMANY           OK 
5     14       RICHARD       6           UNITED STATES     NOT
6     14       ROCKY         7           JAPAN             OK
7     15       CARLOS        8           SPAIN             NOT
8     15       SIDHART       9           BRAZIL            OK

 Out [10]: 
      ID       NAME      ID_COUNTRY     COUNTRY     STATUS
0     14       KWI           1           MEXICO       OK
1     14       NED           2           ITALY        OK
2     14       RICK          3           CANADA       OK
  

Спасибо, что прочитали меня.

Комментарии:

1. Ошибка, которую вы допускаете, заключается в использовании str . Вам нужно: df.iloc[:, [1, 3, 5, 6]] = df.iloc[:, [1, 3, 5, 6]].astype("object")

2. Я знаю, что это можно сделать так, как вы говорите, а также astype("string") . но как я могу решить основную проблему здесь? @Erfan

Ответ №1:

Предполагая, что ваш ввод (вместо использования индекса столбца, я просто использовал имена столбцов для пояснений):

 d = {'ID': [14, 14, 14, 14, 14, 14, 14, 15, 15], 
         'NAME': ['KWI', 'NED', 'RICK', 'NICH', 'DIONIC', 'RICHARD', 'ROCKY', 'CARLOS', 'SIDARTH'], 
         'ID_COUNTRY':[1, 2, 3,4,5,6,7,8,9], 
         'COUNTRY':['MEXICO', 'ITALY', 'CANADA', 'ENGLAND', 'GERMANY', 'UNITED STATES', 'JAPAN', 'SPAIN', 'BRAZIL'], 
         'ID_CITY':[np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan], 
         'CITY':[np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan], 
         'STATUS': ['OK', 'OK', 'OK', 'OK', 'OK', 'NOT', 'OK', 'NOT', 'OK']}
df = pd.DataFrame(data=d)
  

Вы можете привести объект pd к указанному dtype . Для этого вы можете использовать Int64 and str (вместо string в вашем коде) [см. Ссылку].

 df[['ID', 'ID_COUNTRY', 'ID_CITY']] = df[['ID', 'ID_COUNTRY', 'ID_CITY']].astype("Int64")
df[['NAME', 'COUNTRY', 'CITY', 'STATUS']] = df[['NAME', 'COUNTRY', 'CITY', 'STATUS']].astype("str")
  

С помощью временного приведения типов вы можете определить значения NaN. Для этого примите во внимание, что float принимает строки nan с необязательным префиксом или - без числа (NaN).

 df['CITY'].astype("float").isna()
  

Вывод:

 0    True
1    True
2    True
3    True
4    True
5    True
6    True
7    True
8    True
Name: CITY, dtype: bool
  

Либо

 df['ID_CITY'].isna()
  

или

 df['ID_CITY'].astype("float").isna()
  

приведет:

 0    True
1    True
2    True
3    True
4    True
5    True
6    True
7    True
8    True
Name: ID_CITY, dtype: bool