首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >当列包含字符串值时熊猫DataFrame.sum的奇数行为

当列包含字符串值时熊猫DataFrame.sum的奇数行为
EN

Stack Overflow用户
提问于 2018-10-26 09:06:20
回答 2查看 4.5K关注 0票数 3

我有3只熊猫的调查回复数据,它们看起来完全一样,但以不同的方式创建:

代码语言:javascript
运行
复制
import pandas as pd

df1 = pd.DataFrame([[1,2,3],[4,5,'hey'],[7,8,9]])

df2 = pd.DataFrame([[1,2,3],[4,5,6],[7,8,9]])
df2.loc[1,2] = 'hey'

df3 = pd.DataFrame(index=range(3), columns=range(3))
for i in range(3):
    for j in range(3):
        if (i,j) != (1,2):
            df3.loc[i,j] = i*3 + j + 1
        else:
            df3.loc[i,j] = 'hey'

# df1, df2, df3 look the same as below
   0  1    2
0  1  2    3
1  4  5  hey
2  7  8    9

现在,当我沿着列取和时,它们都给出了相同的结果。

代码语言:javascript
运行
复制
sumcol1 = df1.sum()
sumcol2 = df2.sum()
sumcol3 = df3.sum()

# sumcol1, sumcol2, sumcol3 look the same as below
0    12
1    15
dtype: int64

但是,当我在行中取和时,df3给出的结果与df1df2不同。

此外,当axis=0时,似乎不会计算包含字符串的列的和,而当axis=1时,所有行和都将使用属于跳过字符串元素的列的元素计算。

代码语言:javascript
运行
复制
sumrow1 = df1.sum(axis=1)
sumrow2 = df2.sum(axis=1)
sumrow3 = df3.sum(axis=1)

#sumrow1
0     3
1     9
2    15
dtype: int64

#sumrow2
0     3
1     9
2    15
dtype: int64

#sumrow3
0    0.0
1    0.0
2    0.0
dtype: float64

关于这个我有三个问题。

  1. 是什么导致了sumcol1sumrow1的不同行为?
  2. 是什么导致了sumrow1sumrow3的不同行为?
  3. 是否有适当的方法来获得与sumrow1df3相同的结果?

添加:

  1. 在保留字符串的同时,是否有一种只添加数字值的明智方法?
代码语言:javascript
运行
复制
- My current workaround (thanks to jpp's kind answer):

df = pd.DataFrame([1,2,3,4,5,‘嗨’,7,8,9]) df_c = df.copy() in df.select_dtypes('object').columns: df_ccol = pd.to_numeric(df_ccol,errors=‘胁迫’) df' sum‘= df_c.sum(axis=1)结果0 1 2和0 2 3 6 0 1 4 5嘿9.0 2 8 9 24.0

我和Python3.6.6,熊猫0.23.4一起工作。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-10-26 09:17:55

有几个问题:

  • 主要问题是df3的构造包含了使用dtype object的所有三个系列,而df1df2在前两个系列中有dtype=int
  • Pandas中的数据按系列列组织和存储。因此,类型铸造是以串联方式进行的.因此,跨越“行和列”的求和逻辑必然是不同的,并且不一定与混合类型相一致。

要了解第一个问题发生了什么,您必须了解Pandas没有在每次操作之后不断地检查最合适的dtype。这将是令人望而却步的昂贵。

您可以自己检查dtypes

代码语言:javascript
运行
复制
print({'df1': df1.dtypes, 'df2': df2.dtypes, 'df3': df3.dtypes})

{'df1': 0     int64
        1     int64
        2    object
      dtype: object,

 'df2': 0     int64
        1     int64
        2    object
      dtype: object,

 'df3': 0    object
        1    object
        2    object
      dtype: object}

您可以通过一个检查空值是否会导致转换后结果的操作,选择性地将转换应用到df3

代码语言:javascript
运行
复制
for col in df3.select_dtypes(['object']).columns:
    col_num = pd.to_numeric(df3[col], errors='coerce')
    if not col_num.isnull().any():  # check if any null values
        df3[col] = col_num          # assign numeric series

print(df3.dtypes)

0     int64
1     int64
2    object
dtype: object

然后,你应该看到一致的治疗。在这一点上,放弃原始的df3是值得的:在每次操作之后,没有记录连续的系列类型检查可以或应该应用的任何地方。

若要在行或列之间求和时忽略非数字值,可以通过pd.to_numericerrors='coerce'强制转换。

代码语言:javascript
运行
复制
df = pd.DataFrame([[1,2,3],[4,5,'hey'],[7,8,9]])

col_sum = df.apply(pd.to_numeric, errors='coerce').sum()
row_sum = df.apply(pd.to_numeric, errors='coerce').sum(1)

print(col_sum)

0    12.0
1    15.0
2    12.0
dtype: float64

print(row_sum)

0     6.0
1     9.0
2    24.0
dtype: float64
票数 3
EN

Stack Overflow用户

发布于 2018-10-27 01:40:38

根据您的问题和jpp的诊断,数据格式看起来是一样的,但是它们在第3列上的数据类型不同。

以下是一些显示差异的比较方法:

代码语言:javascript
运行
复制
>>> df1.equals(df3)
False # not so useful, doesn't tell you why they differ

您真正需要的是pandas.testing.assert_frame_equal

代码语言:javascript
运行
复制
>>> import pandas.testing
>>> pandas.testing.assert_frame_equal(df1, df3)

AssertionError: Attributes are different

Attribute "dtype" are different
[left]:  int64
[right]: object

pandas.testing.assert_frame_equal()有以下实用args的厨房水槽,您可以定制您需要的任何东西:

代码语言:javascript
运行
复制
check_dtype : bool, default True    
Whether to check the DataFrame dtype is identical.

check_index_type : bool / string {‘equiv’}, default False    
Whether to check the Index class, dtype and inferred_type are identical.

check_column_type : bool / string {‘equiv’}, default False    
Whether to check the columns class, dtype and inferred_type are identical.

check_frame_type : bool, default False    
Whether to check the DataFrame class is identical.

check_less_precise : bool or int, default False    
Specify comparison precision. Only used when check_exact is False. 5 digits (False) or 3 digits (True) after decimal points are compared. If int, then specify the digits to compare

check_names : bool, default True    
Whether to check the Index names attribute.

by_blocks : bool, default False    
Specify how to compare internal data. If False, compare by columns. If True, compare by blocks.

check_exact : bool, default False    
Whether to compare number exactly.

check_datetimelike_compat : bool, default False    
Compare datetime-like which is comparable ignoring dtype.

check_categorical : bool, default True    
Whether to compare internal Categorical exactly.

check_like : bool, default False    
If true, ignore the order of rows & columns
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53005214

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档